|
@@ -50,21 +50,21 @@ export class IVProgProcessor {
|
|
this.function_call_count = 0;
|
|
this.function_call_count = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- registerInput(input) {
|
|
|
|
|
|
+ registerInput (input) {
|
|
if (this.input !== null) this.input = null;
|
|
if (this.input !== null) this.input = null;
|
|
this.input = input;
|
|
this.input = input;
|
|
}
|
|
}
|
|
|
|
|
|
- registerOutput(output) {
|
|
|
|
|
|
+ registerOutput (output) {
|
|
if (this.output !== null) this.output = null;
|
|
if (this.output !== null) this.output = null;
|
|
this.output = output;
|
|
this.output = output;
|
|
}
|
|
}
|
|
|
|
|
|
- checkContext(context) {
|
|
|
|
|
|
+ checkContext (context) {
|
|
return this.context[this.context.length - 1] === context;
|
|
return this.context[this.context.length - 1] === context;
|
|
}
|
|
}
|
|
|
|
|
|
- ignoreSwitchCases(store) {
|
|
|
|
|
|
+ ignoreSwitchCases (store) {
|
|
if (store.mode === Modes.RETURN) {
|
|
if (store.mode === Modes.RETURN) {
|
|
return true;
|
|
return true;
|
|
} else if (store.mode === Modes.BREAK) {
|
|
} else if (store.mode === Modes.BREAK) {
|
|
@@ -74,7 +74,7 @@ export class IVProgProcessor {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- prepareState() {
|
|
|
|
|
|
+ prepareState () {
|
|
if (this.stores !== null) {
|
|
if (this.stores !== null) {
|
|
for (let i = 0; i < this.stores.length; i++) {
|
|
for (let i = 0; i < this.stores.length; i++) {
|
|
delete this.stores[i];
|
|
delete this.stores[i];
|
|
@@ -89,7 +89,7 @@ export class IVProgProcessor {
|
|
this.mode = Modes.RUN;
|
|
this.mode = Modes.RUN;
|
|
}
|
|
}
|
|
|
|
|
|
- async interpretAST() {
|
|
|
|
|
|
+ async interpretAST () {
|
|
this.prepareState();
|
|
this.prepareState();
|
|
Location.clear();
|
|
Location.clear();
|
|
await this.initGlobal();
|
|
await this.initGlobal();
|
|
@@ -100,18 +100,18 @@ export class IVProgProcessor {
|
|
return this.runFunction(mainFunc, [], this.globalStore);
|
|
return this.runFunction(mainFunc, [], this.globalStore);
|
|
}
|
|
}
|
|
|
|
|
|
- async initGlobal() {
|
|
|
|
|
|
+ async initGlobal () {
|
|
if (!this.checkContext(Context.BASE)) {
|
|
if (!this.checkContext(Context.BASE)) {
|
|
return ProcessorErrorFactory.invalid_global_var();
|
|
return ProcessorErrorFactory.invalid_global_var();
|
|
}
|
|
}
|
|
return this.executeCommands(this.globalStore, this.ast.global);
|
|
return this.executeCommands(this.globalStore, this.ast.global);
|
|
}
|
|
}
|
|
|
|
|
|
- findMainFunction() {
|
|
|
|
|
|
+ findMainFunction () {
|
|
return this.ast.functions.find((v) => v.isMain);
|
|
return this.ast.functions.find((v) => v.isMain);
|
|
}
|
|
}
|
|
|
|
|
|
- findFunction(name) {
|
|
|
|
|
|
+ findFunction (name) {
|
|
if (name.match(/^\$.+$/)) {
|
|
if (name.match(/^\$.+$/)) {
|
|
if (name === IVProgProcessor.MAIN_INTERNAL_ID) {
|
|
if (name === IVProgProcessor.MAIN_INTERNAL_ID) {
|
|
return this.findMainFunction();
|
|
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 funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
|
|
const funcStore = new Store(funcName);
|
|
const funcStore = new Store(funcName);
|
|
funcStore.extendStore(this.globalStore);
|
|
funcStore.extendStore(this.globalStore);
|
|
@@ -152,7 +152,7 @@ export class IVProgProcessor {
|
|
return finalSto;
|
|
return finalSto;
|
|
}
|
|
}
|
|
|
|
|
|
- async associateParameters(
|
|
|
|
|
|
+ async associateParameters (
|
|
formal_params,
|
|
formal_params,
|
|
effective_params,
|
|
effective_params,
|
|
caller_store,
|
|
caller_store,
|
|
@@ -256,7 +256,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeCommands(store, cmds) {
|
|
|
|
|
|
+ async executeCommands (store, cmds) {
|
|
// helper to partially apply a function, in this case executeCommand
|
|
// helper to partially apply a function, in this case executeCommand
|
|
let sto = store;
|
|
let sto = store;
|
|
for (let i = 0; i < cmds.length; i += 1) {
|
|
for (let i = 0; i < cmds.length; i += 1) {
|
|
@@ -272,7 +272,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeCommand(store, cmd) {
|
|
|
|
|
|
+ async executeCommand (store, cmd) {
|
|
this.instruction_count += 1;
|
|
this.instruction_count += 1;
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
//every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
|
|
//every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
|
|
@@ -333,7 +333,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeSysCall(store, cmd) {
|
|
|
|
|
|
+ async executeSysCall (store, cmd) {
|
|
const func = cmd.langFunc.bind(this);
|
|
const func = cmd.langFunc.bind(this);
|
|
return func(store, cmd);
|
|
return func(store, cmd);
|
|
}
|
|
}
|
|
@@ -345,7 +345,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeFunctionCall(store, cmd) {
|
|
|
|
|
|
+ async executeFunctionCall (store, cmd) {
|
|
let func = null;
|
|
let func = null;
|
|
if (cmd.isMainCall) {
|
|
if (cmd.isMainCall) {
|
|
func = this.findMainFunction();
|
|
func = this.findMainFunction();
|
|
@@ -377,7 +377,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeSwitch(store, cmd) {
|
|
|
|
|
|
+ async executeSwitch (store, cmd) {
|
|
this.context.push(Context.BREAKABLE);
|
|
this.context.push(Context.BREAKABLE);
|
|
const switchCases = cmd.cases;
|
|
const switchCases = cmd.cases;
|
|
let lastStore = store;
|
|
let lastStore = store;
|
|
@@ -424,7 +424,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeFor(store, cmd) {
|
|
|
|
|
|
+ async executeFor (store, cmd) {
|
|
//BEGIN for -> while rewrite
|
|
//BEGIN for -> while rewrite
|
|
const initCmd = new Commands.Assign(cmd.for_id.id, cmd.for_from);
|
|
const initCmd = new Commands.Assign(cmd.for_id.id, cmd.for_from);
|
|
initCmd.sourceInfo = cmd.sourceInfo;
|
|
initCmd.sourceInfo = cmd.sourceInfo;
|
|
@@ -492,7 +492,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeRepeatUntil(store, cmd) {
|
|
|
|
|
|
+ async executeRepeatUntil (store, cmd) {
|
|
this.context.push(Context.BREAKABLE);
|
|
this.context.push(Context.BREAKABLE);
|
|
const sto = await this.executeCommands(store, cmd.commands);
|
|
const sto = await this.executeCommands(store, cmd.commands);
|
|
if (sto.mode === Modes.BREAK) {
|
|
if (sto.mode === Modes.BREAK) {
|
|
@@ -519,7 +519,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeWhile(store, cmd) {
|
|
|
|
|
|
+ async executeWhile (store, cmd) {
|
|
this.context.push(Context.BREAKABLE);
|
|
this.context.push(Context.BREAKABLE);
|
|
const checkCondition = await this.evaluateExpression(store, cmd.expression);
|
|
const checkCondition = await this.evaluateExpression(store, cmd.expression);
|
|
if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
|
|
if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
|
|
@@ -549,7 +549,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeIfThenElse(store, cmd) {
|
|
|
|
|
|
+ async executeIfThenElse (store, cmd) {
|
|
const isTrue = await this.evaluateExpression(store, cmd.condition);
|
|
const isTrue = await this.evaluateExpression(store, cmd.condition);
|
|
if (!isTrue.type.isCompatible(Types.BOOLEAN)) {
|
|
if (!isTrue.type.isCompatible(Types.BOOLEAN)) {
|
|
throw ProcessorErrorFactory.if_condition_type_full(
|
|
throw ProcessorErrorFactory.if_condition_type_full(
|
|
@@ -577,7 +577,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeReturn(store, cmd) {
|
|
|
|
|
|
+ async executeReturn (store, cmd) {
|
|
const funcName =
|
|
const funcName =
|
|
store.name === IVProgProcessor.MAIN_INTERNAL_ID
|
|
store.name === IVProgProcessor.MAIN_INTERNAL_ID
|
|
? LanguageDefinedFunction.getMainFunctionName()
|
|
? LanguageDefinedFunction.getMainFunctionName()
|
|
@@ -621,7 +621,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeBreak(store, cmd) {
|
|
|
|
|
|
+ async executeBreak (store, cmd) {
|
|
if (this.checkContext(Context.BREAKABLE)) {
|
|
if (this.checkContext(Context.BREAKABLE)) {
|
|
store.mode = Modes.BREAK;
|
|
store.mode = Modes.BREAK;
|
|
return store;
|
|
return store;
|
|
@@ -637,7 +637,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeAssign(store, cmd) {
|
|
|
|
|
|
+ async executeAssign (store, cmd) {
|
|
const inStore = store.applyStore(cmd.id);
|
|
const inStore = store.applyStore(cmd.id);
|
|
if (inStore.isConst) {
|
|
if (inStore.isConst) {
|
|
throw ProcessorErrorFactory.invalid_const_assignment_full(
|
|
throw ProcessorErrorFactory.invalid_const_assignment_full(
|
|
@@ -707,7 +707,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeArrayIndexAssign(store, cmd) {
|
|
|
|
|
|
+ async executeArrayIndexAssign (store, cmd) {
|
|
const mustBeArray = store.applyStore(cmd.id);
|
|
const mustBeArray = store.applyStore(cmd.id);
|
|
let used_dims = 0;
|
|
let used_dims = 0;
|
|
if (mustBeArray.isConst) {
|
|
if (mustBeArray.isConst) {
|
|
@@ -834,7 +834,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeDeclaration(store, cmd) {
|
|
|
|
|
|
+ async executeDeclaration (store, cmd) {
|
|
if (cmd instanceof Commands.ArrayDeclaration) {
|
|
if (cmd instanceof Commands.ArrayDeclaration) {
|
|
return this.executeArrayDeclaration(store, cmd);
|
|
return this.executeArrayDeclaration(store, cmd);
|
|
} else {
|
|
} else {
|
|
@@ -878,7 +878,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<Store>}
|
|
* @returns {Promise<Store>}
|
|
*/
|
|
*/
|
|
- async executeArrayDeclaration(store, cmd) {
|
|
|
|
|
|
+ async executeArrayDeclaration (store, cmd) {
|
|
const linesSV = await this.evaluateExpression(store, cmd.lines);
|
|
const linesSV = await this.evaluateExpression(store, cmd.lines);
|
|
if (!Types.INTEGER.isCompatible(linesSV.type)) {
|
|
if (!Types.INTEGER.isCompatible(linesSV.type)) {
|
|
throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
|
|
throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
|
|
@@ -936,7 +936,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<import('./store/value/istore_value').IStoreValue>}
|
|
* @returns {Promise<import('./store/value/istore_value').IStoreValue>}
|
|
*/
|
|
*/
|
|
- async evaluateExpression(store, exp) {
|
|
|
|
|
|
+ async evaluateExpression (store, exp) {
|
|
this.instruction_count += 1;
|
|
this.instruction_count += 1;
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
if (this.instruction_count % Config.suspend_threshold == 0) {
|
|
//every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
|
|
//every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
|
|
@@ -966,6 +966,8 @@ export class IVProgProcessor {
|
|
return this.evaluateLiteral(store, exp);
|
|
return this.evaluateLiteral(store, exp);
|
|
} else if (exp instanceof Expressions.StringLiteral) {
|
|
} else if (exp instanceof Expressions.StringLiteral) {
|
|
return this.evaluateLiteral(store, exp);
|
|
return this.evaluateLiteral(store, exp);
|
|
|
|
+ } else if (exp instanceof Expressions.CharLiteral) {
|
|
|
|
+ return this.evaluateLiteral(store, exp);
|
|
} else if (exp instanceof Expressions.ArrayLiteral) {
|
|
} else if (exp instanceof Expressions.ArrayLiteral) {
|
|
throw new Error(
|
|
throw new Error(
|
|
"Internal Error: The system should not eval an array literal."
|
|
"Internal Error: The system should not eval an array literal."
|
|
@@ -1015,7 +1017,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<StoreValue[]>}
|
|
* @returns {Promise<StoreValue[]>}
|
|
*/
|
|
*/
|
|
- async evaluateArrayLiteral(store, exp, type, lines, columns) {
|
|
|
|
|
|
+ async evaluateArrayLiteral (store, exp, type, lines, columns) {
|
|
if (!exp.isVector) {
|
|
if (!exp.isVector) {
|
|
if (columns == null) {
|
|
if (columns == null) {
|
|
throw new Error(
|
|
throw new Error(
|
|
@@ -1049,7 +1051,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<StoreValue[]>} store object list
|
|
* @returns {Promise<StoreValue[]>} store object list
|
|
*/
|
|
*/
|
|
- async evaluateVector(store, exps, type, n_elements) {
|
|
|
|
|
|
+ async evaluateVector (store, exps, type, n_elements) {
|
|
const values = exps.value;
|
|
const values = exps.value;
|
|
if (n_elements !== values.length) {
|
|
if (n_elements !== values.length) {
|
|
throw ProcessorErrorFactory.invalid_number_elements_vector(
|
|
throw ProcessorErrorFactory.invalid_number_elements_vector(
|
|
@@ -1092,7 +1094,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {Promise<StoreValue[][]>}
|
|
* @returns {Promise<StoreValue[][]>}
|
|
*/
|
|
*/
|
|
- async evaluateMatrix(store, exps, type, lines, columns) {
|
|
|
|
|
|
+ async evaluateMatrix (store, exps, type, lines, columns) {
|
|
const values = exps.value;
|
|
const values = exps.value;
|
|
if (values.length !== lines) {
|
|
if (values.length !== lines) {
|
|
throw ProcessorErrorFactory.invalid_number_lines_matrix(
|
|
throw ProcessorErrorFactory.invalid_number_lines_matrix(
|
|
@@ -1116,7 +1118,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
*/
|
|
*/
|
|
- async evaluateLiteral(_, exp) {
|
|
|
|
|
|
+ async evaluateLiteral (_, exp) {
|
|
return new StoreValue(exp.type, exp.value);
|
|
return new StoreValue(exp.type, exp.value);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1127,7 +1129,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
*/
|
|
*/
|
|
- async evaluateVariableLiteral(store, exp) {
|
|
|
|
|
|
+ async evaluateVariableLiteral (store, exp) {
|
|
const val = store.applyStore(exp.id);
|
|
const val = store.applyStore(exp.id);
|
|
return val;
|
|
return val;
|
|
}
|
|
}
|
|
@@ -1139,7 +1141,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
*/
|
|
*/
|
|
- async evaluateArrayAccess(store, exp) {
|
|
|
|
|
|
+ async evaluateArrayAccess (store, exp) {
|
|
const mustBeArray = store.getStoreObject(exp.id);
|
|
const mustBeArray = store.getStoreObject(exp.id);
|
|
if (!(mustBeArray.type instanceof ArrayType)) {
|
|
if (!(mustBeArray.type instanceof ArrayType)) {
|
|
throw ProcessorErrorFactory.invalid_array_access_full(
|
|
throw ProcessorErrorFactory.invalid_array_access_full(
|
|
@@ -1243,7 +1245,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
*/
|
|
*/
|
|
- async evaluateUnaryApp(store, unaryApp) {
|
|
|
|
|
|
+ async evaluateUnaryApp (store, unaryApp) {
|
|
const left = await this.evaluateExpression(store, unaryApp.left);
|
|
const left = await this.evaluateExpression(store, unaryApp.left);
|
|
const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
|
|
const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
|
|
if (Types.UNDEFINED.isCompatible(resultType)) {
|
|
if (Types.UNDEFINED.isCompatible(resultType)) {
|
|
@@ -1275,7 +1277,7 @@ export class IVProgProcessor {
|
|
*
|
|
*
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
* @returns {import('./store/value/istore_value').IStoreValue}
|
|
*/
|
|
*/
|
|
- async evaluateInfixApp(store, infixApp) {
|
|
|
|
|
|
+ async evaluateInfixApp (store, infixApp) {
|
|
const left = await this.evaluateExpression(store, infixApp.left);
|
|
const left = await this.evaluateExpression(store, infixApp.left);
|
|
const right = await this.evaluateExpression(store, infixApp.right);
|
|
const right = await this.evaluateExpression(store, infixApp.right);
|
|
let shouldImplicitCast = false;
|
|
let shouldImplicitCast = false;
|