diff --git a/evaluator.js b/evaluator.js index 17c7dba..29518ea 100644 --- a/evaluator.js +++ b/evaluator.js @@ -5,7 +5,7 @@ import { TOKEN, TOKEN_BY_NUMBER, TYPES, - ALL_TYPES + Type } from './functions.js' import {EvaluationError, ParseError, nodePositionCache} from './errors.js' @@ -997,10 +997,8 @@ class Evaluator { } __supportsEqualityOperator(ast) { - const left = (this.left = this.eval(ast[1])) - const right = (this.right = this.eval(ast[2])) - const leftType = debugType(left) - const rightType = debugType(right) + const leftType = debugType((this.left = this.eval(ast[1]))) + const rightType = debugType((this.right = this.eval(ast[2]))) if (leftType === rightType) return // Allow numeric type cross-compatibility for equality/inequality operators @@ -1016,10 +1014,8 @@ class Evaluator { throw new EvaluationError(`no such overload: ${leftType} ${ast[0]} ${rightType}`, ast) } __supportsRelationalOperator(ast) { - const left = (this.left = this.eval(ast[1])) - const right = (this.right = this.eval(ast[2])) - const leftType = debugType(left) - const rightType = debugType(right) + const leftType = debugType((this.left = this.eval(ast[1]))) + const rightType = debugType((this.right = this.eval(ast[2]))) switch (leftType) { case 'Integer': @@ -1038,18 +1034,14 @@ class Evaluator { throw new EvaluationError(`no such overload: ${leftType} ${ast[0]} ${rightType}`, ast) } __verifyNumberOverload(ast) { - const left = (this.left = this.eval(ast[1])) - const right = (this.right = this.eval(ast[2])) - const leftType = debugType(left) - const rightType = debugType(right) + const leftType = debugType((this.left = this.eval(ast[1]))) + const rightType = debugType((this.right = this.eval(ast[2]))) if (leftType === rightType && (leftType === 'Integer' || leftType === 'Double')) return throw new EvaluationError(`no such overload: ${leftType} ${ast[0]} ${rightType}`, ast) } __verifyIntOverload(ast) { - const left = (this.left = this.eval(ast[1])) - const right = (this.right = this.eval(ast[2])) - const leftType = debugType(left) - const rightType = debugType(right) + const leftType = debugType((this.left = this.eval(ast[1]))) + const rightType = debugType((this.right = this.eval(ast[2]))) if (leftType === rightType && leftType === 'Integer') return throw new EvaluationError(`no such overload: ${leftType} ${ast[0]} ${rightType}`, ast) } @@ -1189,15 +1181,13 @@ function debugType(v) { return 'Double' case 'boolean': return 'Boolean' - case 'symbol': - if (ALL_TYPES.has(v)) return 'Type' - break case 'object': if (v === null) return 'null' if (v.constructor === Object || v instanceof Map || !v.constructor) return 'Map' if (Array.isArray(v)) return 'List' if (v instanceof Uint8Array) return 'Bytes' if (v instanceof Date) return 'Timestamp' + if (v instanceof Type) return 'Type' } throw new EvaluationError(`Unsupported type: ${v?.constructor?.name || typeof v}`) } diff --git a/functions.js b/functions.js index 118a068..e957c8c 100644 --- a/functions.js +++ b/functions.js @@ -1,18 +1,32 @@ import {EvaluationError} from './errors.js' -export const TYPES = { - string: Symbol('String'), - bool: Symbol('Boolean'), - int: Symbol('Integer'), - double: Symbol('Double'), - map: Symbol('Map'), - list: Symbol('List'), - bytes: Symbol('Bytes'), - null_type: Symbol('null'), - type: Symbol('Type') +export class Type { + #name + constructor(name) { + this.#name = name + } + + get [Symbol.toStringTag]() { + return `Type<${this.#name}>` + } + + toString() { + return `Type<${this.#name}>` + } } -export const ALL_TYPES = new Set(Object.values(TYPES)) +export const TYPES = { + string: new Type('String'), + bool: new Type('Boolean'), + int: new Type('Integer'), + double: new Type('Double'), + map: new Type('Map'), + list: new Type('List'), + bytes: new Type('Bytes'), + null_type: new Type('null'), + type: new Type('Type'), + 'google.protobuf.Timestamp': new Type('google.protobuf.Timestamp') +} export const TOKEN = { EOF: 0, @@ -178,15 +192,13 @@ registerFunction({ return TYPES.double case 'boolean': return TYPES.bool - case 'symbol': - if (ALL_TYPES.has(v)) return TYPES.type - break case 'object': if (v === null) return TYPES.null_type if (v.constructor === Object || v instanceof Map || !v.constructor) return TYPES.map if (Array.isArray(v)) return TYPES.list if (v instanceof Uint8Array) return TYPES.bytes - if (v instanceof Date) return TYPES.TIMESTAMP + if (v instanceof Date) return TYPES['google.protobuf.Timestamp'] + if (v instanceof Type) return TYPES.type } throw new EvaluationError(`Unsupported type: ${v?.constructor?.name || typeof v}`) }