|
@@ -29,11 +29,11 @@ import { StoreValueAddress } from "./store/value/store_value_address";
|
|
|
import { LocalizedStrings } from "../services/localizedStringsService";
|
|
|
|
|
|
export class IVProgProcessor {
|
|
|
- static get MAIN_INTERNAL_ID() {
|
|
|
+ static get MAIN_INTERNAL_ID () {
|
|
|
return "$main";
|
|
|
}
|
|
|
|
|
|
- constructor(ast) {
|
|
|
+ constructor (ast) {
|
|
|
this.ast = ast;
|
|
|
this.globalStore = new Store("$global");
|
|
|
this.stores = [this.globalStore];
|
|
@@ -50,21 +50,21 @@ export class IVProgProcessor {
|
|
|
this.function_call_count = 0;
|
|
|
}
|
|
|
|
|
|
- registerInput(input) {
|
|
|
+ registerInput (input) {
|
|
|
if (this.input !== null) this.input = null;
|
|
|
this.input = input;
|
|
|
}
|
|
|
|
|
|
- registerOutput(output) {
|
|
|
+ registerOutput (output) {
|
|
|
if (this.output !== null) this.output = null;
|
|
|
this.output = output;
|
|
|
}
|
|
|
|
|
|
- checkContext(context) {
|
|
|
+ checkContext (context) {
|
|
|
return this.context[this.context.length - 1] === context;
|
|
|
}
|
|
|
|
|
|
- ignoreSwitchCases(store) {
|
|
|
+ ignoreSwitchCases (store) {
|
|
|
if (store.mode === Modes.RETURN) {
|
|
|
return true;
|
|
|
} else if (store.mode === Modes.BREAK) {
|
|
@@ -74,7 +74,7 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- prepareState() {
|
|
|
+ prepareState () {
|
|
|
if (this.stores !== null) {
|
|
|
for (let i = 0; i < this.stores.length; i++) {
|
|
|
delete this.stores[i];
|
|
@@ -89,7 +89,7 @@ export class IVProgProcessor {
|
|
|
this.mode = Modes.RUN;
|
|
|
}
|
|
|
|
|
|
- async interpretAST() {
|
|
|
+ async interpretAST () {
|
|
|
this.prepareState();
|
|
|
Location.clear();
|
|
|
await this.initGlobal();
|
|
@@ -100,18 +100,18 @@ export class IVProgProcessor {
|
|
|
return this.runFunction(mainFunc, [], this.globalStore);
|
|
|
}
|
|
|
|
|
|
- async initGlobal() {
|
|
|
+ async initGlobal () {
|
|
|
if (!this.checkContext(Context.BASE)) {
|
|
|
return ProcessorErrorFactory.invalid_global_var();
|
|
|
}
|
|
|
return this.executeCommands(this.globalStore, this.ast.global);
|
|
|
}
|
|
|
|
|
|
- findMainFunction() {
|
|
|
+ findMainFunction () {
|
|
|
return this.ast.functions.find((v) => v.isMain);
|
|
|
}
|
|
|
|
|
|
- findFunction(name) {
|
|
|
+ findFunction (name) {
|
|
|
if (name.match(/^\$.+$/)) {
|
|
|
if (name === IVProgProcessor.MAIN_INTERNAL_ID) {
|
|
|
return this.findMainFunction();
|
|
@@ -130,7 +130,7 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async runFunction(func, actualParameters, store) {
|
|
|
+ async runFunction (func, actualParameters, store) {
|
|
|
const funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
|
|
|
const funcStore = new Store(funcName);
|
|
|
funcStore.extendStore(this.globalStore);
|
|
@@ -153,13 +153,13 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
|
|
|
- *
|
|
|
- * @param {import('./../ast/commands/formalParameter').FormalParameter[]} formal_params
|
|
|
- * @param {Expression[]} effective_params
|
|
|
- * @param {Store} caller_store
|
|
|
- * @param {Store} callee_store
|
|
|
+ *
|
|
|
+ * @param {import('./../ast/commands/formalParameter').FormalParameter[]} formal_params
|
|
|
+ * @param {Expression[]} effective_params
|
|
|
+ * @param {Store} caller_store
|
|
|
+ * @param {Store} callee_store
|
|
|
*/
|
|
|
- async associateParameters(
|
|
|
+ async associateParameters (
|
|
|
formal_params,
|
|
|
effective_params,
|
|
|
caller_store,
|
|
@@ -170,47 +170,76 @@ export class IVProgProcessor {
|
|
|
? LanguageDefinedFunction.getMainFunctionName()
|
|
|
: callee_store.name;
|
|
|
|
|
|
- const hasVariadic = formal_params.some(p => p.variadic);
|
|
|
+ const hasVariadic = formal_params.some((p) => p.variadic);
|
|
|
|
|
|
- if ((formal_params.length != effective_params.length && !hasVariadic)
|
|
|
- || formal_params.length > effective_params.length) {
|
|
|
+ if (
|
|
|
+ (formal_params.length != effective_params.length && !hasVariadic) ||
|
|
|
+ formal_params.length > effective_params.length
|
|
|
+ ) {
|
|
|
throw ProcessorErrorFactory.invalid_parameters_size(
|
|
|
funcName,
|
|
|
formal_params.length,
|
|
|
effective_params.length
|
|
|
);
|
|
|
}
|
|
|
- for (let i = 0, j = 0; i < formal_params.length && j < effective_params.length; i += 1, j += 1) {
|
|
|
+ for (
|
|
|
+ let i = 0, j = 0;
|
|
|
+ i < formal_params.length && j < effective_params.length;
|
|
|
+ i += 1, j += 1
|
|
|
+ ) {
|
|
|
const formalParameter = formal_params[i];
|
|
|
if (formalParameter.variadic) {
|
|
|
- [j, callee_store] = await this.associateVariadicParameter(funcName, formalParameter, j, effective_params, caller_store,
|
|
|
- callee_store);
|
|
|
+ [j, callee_store] = await this.associateVariadicParameter(
|
|
|
+ funcName,
|
|
|
+ formalParameter,
|
|
|
+ j,
|
|
|
+ effective_params,
|
|
|
+ caller_store,
|
|
|
+ callee_store
|
|
|
+ );
|
|
|
} else {
|
|
|
const actualParam = effective_params[i];
|
|
|
- callee_store = await this.associateParameter(funcName, formalParameter, actualParam, caller_store,
|
|
|
- callee_store);
|
|
|
+ callee_store = await this.associateParameter(
|
|
|
+ funcName,
|
|
|
+ formalParameter,
|
|
|
+ actualParam,
|
|
|
+ caller_store,
|
|
|
+ callee_store
|
|
|
+ );
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
return callee_store;
|
|
|
}
|
|
|
|
|
|
|
|
|
- *
|
|
|
- * @param {string} funcName
|
|
|
- * @param {import('./../ast/commands/formalParameter').FormalParameter} formalParameter
|
|
|
- * @param {number} index
|
|
|
- * @param {Expression[]} effective_params
|
|
|
- * @param {Store} caller_store
|
|
|
- * @param {Store} callee_store
|
|
|
+ *
|
|
|
+ * @param {string} funcName
|
|
|
+ * @param {import('./../ast/commands/formalParameter').FormalParameter} formalParameter
|
|
|
+ * @param {number} index
|
|
|
+ * @param {Expression[]} effective_params
|
|
|
+ * @param {Store} caller_store
|
|
|
+ * @param {Store} callee_store
|
|
|
*/
|
|
|
- async associateVariadicParameter (funcName, formalParameter, index, effective_params, caller_store, callee_store) {
|
|
|
+ async associateVariadicParameter (
|
|
|
+ funcName,
|
|
|
+ formalParameter,
|
|
|
+ index,
|
|
|
+ effective_params,
|
|
|
+ caller_store,
|
|
|
+ callee_store
|
|
|
+ ) {
|
|
|
let i;
|
|
|
- let count = 1
|
|
|
+ let count = 1;
|
|
|
for (i = index; i < effective_params.length; i += 1) {
|
|
|
const actualParam = effective_params[i];
|
|
|
- callee_store = await this.associateParameter(funcName, formalParameter, actualParam, caller_store,
|
|
|
- callee_store, count);
|
|
|
+ callee_store = await this.associateParameter(
|
|
|
+ funcName,
|
|
|
+ formalParameter,
|
|
|
+ actualParam,
|
|
|
+ caller_store,
|
|
|
+ callee_store,
|
|
|
+ count
|
|
|
+ );
|
|
|
count += 1;
|
|
|
}
|
|
|
const variadicCount = new StoreValue(Types.INTEGER, count, undefined, true);
|
|
@@ -219,15 +248,18 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
|
|
|
- *
|
|
|
- * @param {string} funcName
|
|
|
- * @param {import('./../ast/commands/formalParameter').FormalParameter} formalParameter
|
|
|
- * @param {Expression} actualParameter
|
|
|
- * @param {Store} callerStore
|
|
|
- * @param {Store} calleeStore
|
|
|
+ *
|
|
|
+ * @param {string} funcName
|
|
|
+ * @param {import('./../ast/commands/formalParameter').FormalParameter} formalParameter
|
|
|
+ * @param {Expression} actualParameter
|
|
|
+ * @param {Store} callerStore
|
|
|
+ * @param {Store} calleeStore
|
|
|
* @param {number} variadicCount The number of the current value being assigned to the variadic parameter, default 0
|
|
|
*/
|
|
|
- async associateParameter (funcName, formalParameter, actualParameter,
|
|
|
+ async associateParameter (
|
|
|
+ funcName,
|
|
|
+ formalParameter,
|
|
|
+ actualParameter,
|
|
|
callerStore,
|
|
|
calleeStore,
|
|
|
variadicCount = 0
|
|
@@ -238,7 +270,7 @@ export class IVProgProcessor {
|
|
|
);
|
|
|
|
|
|
let shouldTypeCast = false;
|
|
|
-
|
|
|
+
|
|
|
if (!formalParameter.type.isCompatible(actualValue.type)) {
|
|
|
if (
|
|
|
Config.enable_type_casting &&
|
|
@@ -255,7 +287,10 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
if (formalParameter.byRef && !actualValue.inStore()) {
|
|
|
- throw ProcessorErrorFactory.invalid_ref(funcName, actualParameter.toString());
|
|
|
+ throw ProcessorErrorFactory.invalid_ref(
|
|
|
+ funcName,
|
|
|
+ actualParameter.toString()
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
if (formalParameter.byRef) {
|
|
@@ -298,8 +333,7 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
}
|
|
|
let varID = formalParameter.id;
|
|
|
- if (formalParameter.variadic)
|
|
|
- varID = `${varID}.${variadicCount}`;
|
|
|
+ if (formalParameter.variadic) varID = `${varID}.${variadicCount}`;
|
|
|
calleeStore.insertStore(varID, ref);
|
|
|
} else {
|
|
|
let realValue = actualValue;
|
|
@@ -307,8 +341,7 @@ export class IVProgProcessor {
|
|
|
realValue = Store.doImplicitCasting(formalParameter.type, realValue);
|
|
|
}
|
|
|
let varID = formalParameter.id;
|
|
|
- if (formalParameter.variadic)
|
|
|
- varID = `${varID}.${variadicCount}`;
|
|
|
+ if (formalParameter.variadic) varID = `${varID}.${variadicCount}`;
|
|
|
calleeStore.insertStore(varID, realValue);
|
|
|
}
|
|
|
return calleeStore;
|
|
@@ -321,7 +354,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeCommands(store, cmds) {
|
|
|
+ async executeCommands (store, cmds) {
|
|
|
|
|
|
let sto = store;
|
|
|
for (let i = 0; i < cmds.length; i += 1) {
|
|
@@ -337,7 +370,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeCommand(store, cmd) {
|
|
|
+ async executeCommand (store, cmd) {
|
|
|
this.instruction_count += 1;
|
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
|
|
|
@@ -398,7 +431,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeSysCall(store, cmd) {
|
|
|
+ async executeSysCall (store, cmd) {
|
|
|
const func = cmd.langFunc.bind(this);
|
|
|
return func(store, cmd);
|
|
|
}
|
|
@@ -410,7 +443,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeFunctionCall(store, cmd) {
|
|
|
+ async executeFunctionCall (store, cmd) {
|
|
|
let func = null;
|
|
|
if (cmd.isMainCall) {
|
|
|
func = this.findMainFunction();
|
|
@@ -442,7 +475,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeSwitch(store, cmd) {
|
|
|
+ async executeSwitch (store, cmd) {
|
|
|
this.context.push(Context.BREAKABLE);
|
|
|
const switchCases = cmd.cases;
|
|
|
let lastStore = store;
|
|
@@ -489,7 +522,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeFor(store, cmd) {
|
|
|
+ async executeFor (store, cmd) {
|
|
|
|
|
|
const initCmd = new Commands.Assign(cmd.for_id.id, cmd.for_from);
|
|
|
initCmd.sourceInfo = cmd.sourceInfo;
|
|
@@ -557,7 +590,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeRepeatUntil(store, cmd) {
|
|
|
+ async executeRepeatUntil (store, cmd) {
|
|
|
this.context.push(Context.BREAKABLE);
|
|
|
const sto = await this.executeCommands(store, cmd.commands);
|
|
|
if (sto.mode === Modes.BREAK) {
|
|
@@ -584,7 +617,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeWhile(store, cmd) {
|
|
|
+ async executeWhile (store, cmd) {
|
|
|
this.context.push(Context.BREAKABLE);
|
|
|
const checkCondition = await this.evaluateExpression(store, cmd.expression);
|
|
|
if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
|
|
@@ -614,7 +647,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeIfThenElse(store, cmd) {
|
|
|
+ async executeIfThenElse (store, cmd) {
|
|
|
const isTrue = await this.evaluateExpression(store, cmd.condition);
|
|
|
if (!isTrue.type.isCompatible(Types.BOOLEAN)) {
|
|
|
throw ProcessorErrorFactory.if_condition_type_full(
|
|
@@ -642,7 +675,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeReturn(store, cmd) {
|
|
|
+ async executeReturn (store, cmd) {
|
|
|
const funcName =
|
|
|
store.name === IVProgProcessor.MAIN_INTERNAL_ID
|
|
|
? LanguageDefinedFunction.getMainFunctionName()
|
|
@@ -686,7 +719,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeBreak(store, cmd) {
|
|
|
+ async executeBreak (store, cmd) {
|
|
|
if (this.checkContext(Context.BREAKABLE)) {
|
|
|
store.mode = Modes.BREAK;
|
|
|
return store;
|
|
@@ -702,7 +735,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeAssign(store, cmd) {
|
|
|
+ async executeAssign (store, cmd) {
|
|
|
const inStore = store.applyStore(cmd.id);
|
|
|
if (inStore.isConst) {
|
|
|
throw ProcessorErrorFactory.invalid_const_assignment_full(
|
|
@@ -772,7 +805,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeArrayIndexAssign(store, cmd) {
|
|
|
+ async executeArrayIndexAssign (store, cmd) {
|
|
|
const mustBeArray = store.applyStore(cmd.id);
|
|
|
let used_dims = 0;
|
|
|
if (mustBeArray.isConst) {
|
|
@@ -899,7 +932,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeDeclaration(store, cmd) {
|
|
|
+ async executeDeclaration (store, cmd) {
|
|
|
if (cmd instanceof Commands.ArrayDeclaration) {
|
|
|
return this.executeArrayDeclaration(store, cmd);
|
|
|
} else {
|
|
@@ -943,7 +976,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<Store>}
|
|
|
*/
|
|
|
- async executeArrayDeclaration(store, cmd) {
|
|
|
+ async executeArrayDeclaration (store, cmd) {
|
|
|
const linesSV = await this.evaluateExpression(store, cmd.lines);
|
|
|
if (!Types.INTEGER.isCompatible(linesSV.type)) {
|
|
|
throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
|
|
@@ -1001,7 +1034,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<import('./store/value/istore_value').IStoreValue>}
|
|
|
*/
|
|
|
- async evaluateExpression(store, exp) {
|
|
|
+ async evaluateExpression (store, exp) {
|
|
|
this.instruction_count += 1;
|
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
|
|
|
@@ -1031,6 +1064,8 @@ export class IVProgProcessor {
|
|
|
return this.evaluateLiteral(store, exp);
|
|
|
} else if (exp instanceof Expressions.StringLiteral) {
|
|
|
return this.evaluateLiteral(store, exp);
|
|
|
+ } else if (exp instanceof Expressions.CharLiteral) {
|
|
|
+ return this.evaluateLiteral(store, exp);
|
|
|
} else if (exp instanceof Expressions.ArrayLiteral) {
|
|
|
throw new Error(
|
|
|
"Internal Error: The system should not eval an array literal."
|
|
@@ -1041,7 +1076,7 @@ export class IVProgProcessor {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- async evaluateFunctionCall(store, exp) {
|
|
|
+ async evaluateFunctionCall (store, exp) {
|
|
|
if (exp.isMainCall) {
|
|
|
throw ProcessorErrorFactory.void_in_expression_full(
|
|
|
LanguageDefinedFunction.getMainFunctionName(),
|
|
@@ -1080,7 +1115,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<StoreValue[]>}
|
|
|
*/
|
|
|
- async evaluateArrayLiteral(store, exp, type, lines, columns) {
|
|
|
+ async evaluateArrayLiteral (store, exp, type, lines, columns) {
|
|
|
if (!exp.isVector) {
|
|
|
if (columns == null) {
|
|
|
throw new Error(
|
|
@@ -1114,7 +1149,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<StoreValue[]>} store object list
|
|
|
*/
|
|
|
- async evaluateVector(store, exps, type, n_elements) {
|
|
|
+ async evaluateVector (store, exps, type, n_elements) {
|
|
|
const values = exps.value;
|
|
|
if (n_elements !== values.length) {
|
|
|
throw ProcessorErrorFactory.invalid_number_elements_vector(
|
|
@@ -1157,7 +1192,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {Promise<StoreValue[][]>}
|
|
|
*/
|
|
|
- async evaluateMatrix(store, exps, type, lines, columns) {
|
|
|
+ async evaluateMatrix (store, exps, type, lines, columns) {
|
|
|
const values = exps.value;
|
|
|
if (values.length !== lines) {
|
|
|
throw ProcessorErrorFactory.invalid_number_lines_matrix(
|
|
@@ -1181,7 +1216,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
|
*/
|
|
|
- async evaluateLiteral(_, exp) {
|
|
|
+ async evaluateLiteral (_, exp) {
|
|
|
return new StoreValue(exp.type, exp.value);
|
|
|
}
|
|
|
|
|
@@ -1192,7 +1227,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
|
*/
|
|
|
- async evaluateVariableLiteral(store, exp) {
|
|
|
+ async evaluateVariableLiteral (store, exp) {
|
|
|
const val = store.applyStore(exp.id);
|
|
|
return val;
|
|
|
}
|
|
@@ -1204,7 +1239,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
|
*/
|
|
|
- async evaluateArrayAccess(store, exp) {
|
|
|
+ async evaluateArrayAccess (store, exp) {
|
|
|
const mustBeArray = store.getStoreObject(exp.id);
|
|
|
if (!(mustBeArray.type instanceof ArrayType)) {
|
|
|
throw ProcessorErrorFactory.invalid_array_access_full(
|
|
@@ -1308,7 +1343,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
|
*/
|
|
|
- async evaluateUnaryApp(store, unaryApp) {
|
|
|
+ async evaluateUnaryApp (store, unaryApp) {
|
|
|
const left = await this.evaluateExpression(store, unaryApp.left);
|
|
|
const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
|
|
|
if (Types.UNDEFINED.isCompatible(resultType)) {
|
|
@@ -1340,7 +1375,7 @@ export class IVProgProcessor {
|
|
|
*
|
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
|
*/
|
|
|
- async evaluateInfixApp(store, infixApp) {
|
|
|
+ async evaluateInfixApp (store, infixApp) {
|
|
|
const left = await this.evaluateExpression(store, infixApp.left);
|
|
|
const right = await this.evaluateExpression(store, infixApp.right);
|
|
|
let shouldImplicitCast = false;
|
|
@@ -1375,6 +1410,10 @@ export class IVProgProcessor {
|
|
|
} else if (Types.STRING.isCompatible(right.type)) {
|
|
|
const leftStr = convertToString(left.get(), left.type);
|
|
|
return new StoreValue(resultType, leftStr + right.get());
|
|
|
+ } else if (Types.CHAR.isCompatible(left.type)) {
|
|
|
+ const strLeft = convertToString(left.get(), left.type);
|
|
|
+ const strRight = convertToString(right.get(), right.type);
|
|
|
+ return new StoreValue(resultType, strLeft + strRight);
|
|
|
} else {
|
|
|
return new StoreValue(resultType, left.get().plus(right.get()));
|
|
|
}
|
|
@@ -1413,6 +1452,8 @@ export class IVProgProcessor {
|
|
|
let rightValue = right.get();
|
|
|
if (Types.STRING.isCompatible(left.type)) {
|
|
|
result = leftValue.length > rightValue.length;
|
|
|
+ } else if (Types.CHAR.isCompatible(left.type)) {
|
|
|
+ result = leftValue.charCodeAt(0) > rightValue.charCodeAt(0);
|
|
|
} else {
|
|
|
if (shouldImplicitCast) {
|
|
|
resultType = Types.BOOLEAN;
|
|
@@ -1428,6 +1469,8 @@ export class IVProgProcessor {
|
|
|
let rightValue = right.get();
|
|
|
if (Types.STRING.isCompatible(left.type)) {
|
|
|
result = leftValue.length >= rightValue.length;
|
|
|
+ } else if (Types.CHAR.isCompatible(left.type)) {
|
|
|
+ result = leftValue.charCodeAt(0) >= rightValue.charCodeAt(0);
|
|
|
} else {
|
|
|
if (shouldImplicitCast) {
|
|
|
resultType = Types.BOOLEAN;
|
|
@@ -1443,6 +1486,8 @@ export class IVProgProcessor {
|
|
|
let rightValue = right.get();
|
|
|
if (Types.STRING.isCompatible(left.type)) {
|
|
|
result = leftValue.length < rightValue.length;
|
|
|
+ } else if (Types.CHAR.isCompatible(left.type)) {
|
|
|
+ result = leftValue.charCodeAt(0) < rightValue.charCodeAt(0);
|
|
|
} else {
|
|
|
if (shouldImplicitCast) {
|
|
|
resultType = Types.BOOLEAN;
|
|
@@ -1458,6 +1503,8 @@ export class IVProgProcessor {
|
|
|
let rightValue = right.get();
|
|
|
if (Types.STRING.isCompatible(left.type)) {
|
|
|
result = leftValue.length <= rightValue.length;
|
|
|
+ } else if (Types.CHAR.isCompatible(left.type)) {
|
|
|
+ result = leftValue.charCodeAt(0) <= rightValue.charCodeAt(0);
|
|
|
} else {
|
|
|
if (shouldImplicitCast) {
|
|
|
resultType = Types.BOOLEAN;
|