|
@@ -5,6 +5,7 @@ import { Types } from "../typeSystem/types";
|
|
import { convertBoolToString } from "../typeSystem/parsers";
|
|
import { convertBoolToString } from "../typeSystem/parsers";
|
|
import * as Commands from "../ast/commands";
|
|
import * as Commands from "../ast/commands";
|
|
import { ArrayType } from "../typeSystem/array_type";
|
|
import { ArrayType } from "../typeSystem/array_type";
|
|
|
|
+import { Literal } from "../ast/expressions/literal";
|
|
|
|
|
|
const TYPES = {
|
|
const TYPES = {
|
|
VARIABLE: "var",
|
|
VARIABLE: "var",
|
|
@@ -54,33 +55,33 @@ function getOpType (op) {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @param {Commands.IfThenElse} ifthenelse
|
|
|
|
- * */
|
|
|
|
|
|
+ * @param {Commands.IfThenElse} ifthenelse
|
|
|
|
+ * */
|
|
function ifThenElseWalker (ifthenelse) {
|
|
function ifThenElseWalker (ifthenelse) {
|
|
//ifthenelse.
|
|
//ifthenelse.
|
|
const expression = expressionWalker(ifthenelse.condition);
|
|
const expression = expressionWalker(ifthenelse.condition);
|
|
- const ifTrue = ifthenelse.ifTrue.commands.map(commandWalker)
|
|
|
|
|
|
+ const ifTrue = ifthenelse.ifTrue.commands.map(commandWalker);
|
|
let ifFalse = [];
|
|
let ifFalse = [];
|
|
if (ifthenelse.ifFalse) {
|
|
if (ifthenelse.ifFalse) {
|
|
if (ifthenelse.ifFalse instanceof Commands.CommandBlock) {
|
|
if (ifthenelse.ifFalse instanceof Commands.CommandBlock) {
|
|
- ifFalse = ifthenelse.ifFalse.commands.map(commandWalker)
|
|
|
|
|
|
+ ifFalse = ifthenelse.ifFalse.commands.map(commandWalker);
|
|
} else {
|
|
} else {
|
|
- ifFalse = [ifThenElseWalker(ifthenelse.ifFalse)]
|
|
|
|
|
|
+ ifFalse = [ifThenElseWalker(ifthenelse.ifFalse)];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
return {
|
|
type: "iftrue",
|
|
type: "iftrue",
|
|
expression,
|
|
expression,
|
|
ifTrue,
|
|
ifTrue,
|
|
- ifFalse
|
|
|
|
- }
|
|
|
|
|
|
+ ifFalse,
|
|
|
|
+ };
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @param {Commands.Assign} assingment
|
|
|
|
- * */
|
|
|
|
|
|
+ * @param {Commands.Assign} assingment
|
|
|
|
+ * */
|
|
function assignmentWalker (assingment) {
|
|
function assignmentWalker (assingment) {
|
|
- let variable = null
|
|
|
|
|
|
+ let variable = null;
|
|
if (assingment instanceof Commands.ArrayIndexAssign) {
|
|
if (assingment instanceof Commands.ArrayIndexAssign) {
|
|
const line = expressionWalker(assingment.line);
|
|
const line = expressionWalker(assingment.line);
|
|
let arrayClass = "vector";
|
|
let arrayClass = "vector";
|
|
@@ -102,57 +103,63 @@ function assignmentWalker (assingment) {
|
|
} else {
|
|
} else {
|
|
variable = [
|
|
variable = [
|
|
{ instance: "expression", type: TYPES.VARIABLE, value: assingment.id },
|
|
{ instance: "expression", type: TYPES.VARIABLE, value: assingment.id },
|
|
- ]
|
|
|
|
|
|
+ ];
|
|
}
|
|
}
|
|
- const expression = expressionWalker(assingment.expression)
|
|
|
|
|
|
+ const expression = expressionWalker(assingment.expression);
|
|
return {
|
|
return {
|
|
type: "attribution",
|
|
type: "attribution",
|
|
variable,
|
|
variable,
|
|
- expression
|
|
|
|
- }
|
|
|
|
|
|
+ expression,
|
|
|
|
+ };
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* @param {Command} command
|
|
* @param {Command} command
|
|
- * */
|
|
|
|
|
|
+ * */
|
|
function commandWalker (command) {
|
|
function commandWalker (command) {
|
|
if (command instanceof Commands.FunctionCall) {
|
|
if (command instanceof Commands.FunctionCall) {
|
|
- return functionCallWalker(command)
|
|
|
|
|
|
+ return functionCallWalker(command);
|
|
} else if (command instanceof Commands.Assign) {
|
|
} else if (command instanceof Commands.Assign) {
|
|
- return assignmentWalker(command)
|
|
|
|
|
|
+ return assignmentWalker(command);
|
|
} else if (command instanceof Commands.IfThenElse) {
|
|
} else if (command instanceof Commands.IfThenElse) {
|
|
- return ifThenElseWalker(command)
|
|
|
|
|
|
+ return ifThenElseWalker(command);
|
|
}
|
|
}
|
|
- throw new Error("not implemented")
|
|
|
|
|
|
+ throw new Error("not implemented");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* @param {Commands.FunctionCall} functionCall
|
|
* @param {Commands.FunctionCall} functionCall
|
|
- * */
|
|
|
|
|
|
+ * */
|
|
function functionCallWalker (functionCall) {
|
|
function functionCallWalker (functionCall) {
|
|
let name = functionCall.id;
|
|
let name = functionCall.id;
|
|
if (name.indexOf(".") !== -1) {
|
|
if (name.indexOf(".") !== -1) {
|
|
- name = name.split(".")[1]
|
|
|
|
- }
|
|
|
|
- if (name === "$read") {
|
|
|
|
- const variable = functionCall.actualParameters.map(expressionWalker)[0]
|
|
|
|
- return {
|
|
|
|
- type:"reader",
|
|
|
|
- variable
|
|
|
|
- }
|
|
|
|
|
|
+ name = name.split(".")[1];
|
|
}
|
|
}
|
|
|
|
+ const parameters = functionCall.actualParameters.map(expressionWalker);
|
|
if (name === "$write") {
|
|
if (name === "$write") {
|
|
- const content = functionCall.actualParameters.map(expressionWalker)
|
|
|
|
- const lastInput = content[content.length - 1][0];
|
|
|
|
|
|
+ const lastInput = parameters[parameters.length - 1][0];
|
|
// if lastInput is an object with value === '\n', newLine is true
|
|
// if lastInput is an object with value === '\n', newLine is true
|
|
- const newLine = lastInput.value && lastInput.value.match(/\n/) !== null
|
|
|
|
|
|
+ const newLine = lastInput.value && lastInput.value.match(/^\n$/) !== null;
|
|
|
|
+ const content = newLine
|
|
|
|
+ ? parameters.slice(0, parameters.length - 1)
|
|
|
|
+ : parameters;
|
|
return {
|
|
return {
|
|
- type:"writer",
|
|
|
|
|
|
+ type: "writer",
|
|
newLine,
|
|
newLine,
|
|
- content
|
|
|
|
- }
|
|
|
|
|
|
+ content,
|
|
|
|
+ };
|
|
}
|
|
}
|
|
- throw new Error("not implemented")
|
|
|
|
|
|
+ if (name === "$read") {
|
|
|
|
+ return {
|
|
|
|
+ type: "reader",
|
|
|
|
+ variable: parameters[0],
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ type: "functioncall",
|
|
|
|
+ parameters_list: parameters,
|
|
|
|
+ name: functionCall.id,
|
|
|
|
+ };
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* @param {Commands.Function} func
|
|
* @param {Commands.Function} func
|
|
@@ -178,7 +185,7 @@ function functionWalker (func) {
|
|
funcDeclaration.variables_list = func.variablesDeclarations.map(
|
|
funcDeclaration.variables_list = func.variablesDeclarations.map(
|
|
variableDeclarationWalker
|
|
variableDeclarationWalker
|
|
);
|
|
);
|
|
- funcDeclaration.commands = func.commands.map(commandWalker)
|
|
|
|
|
|
+ funcDeclaration.commands = func.commands.map(commandWalker);
|
|
return funcDeclaration;
|
|
return funcDeclaration;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -225,11 +232,10 @@ function variableDeclarationWalker (command, global = false) {
|
|
const lines = expressionWalker(command.lines).pop();
|
|
const lines = expressionWalker(command.lines).pop();
|
|
variable.type = command.type.innerType.value;
|
|
variable.type = command.type.innerType.value;
|
|
if (command.isVector) {
|
|
if (command.isVector) {
|
|
- variable.rows = 1;
|
|
|
|
variable.columns = lines.value;
|
|
variable.columns = lines.value;
|
|
variable.dimension = 1;
|
|
variable.dimension = 1;
|
|
- const values = command.initial.map(
|
|
|
|
- (exp) => expressionWalker(exp).pop().value
|
|
|
|
|
|
+ const values = command.initial.value.map((exp) =>
|
|
|
|
+ variableInitialWalker(exp)
|
|
);
|
|
);
|
|
variable.value = values;
|
|
variable.value = values;
|
|
} else {
|
|
} else {
|
|
@@ -237,19 +243,52 @@ function variableDeclarationWalker (command, global = false) {
|
|
variable.dimension = 2;
|
|
variable.dimension = 2;
|
|
variable.rows = lines.value;
|
|
variable.rows = lines.value;
|
|
variable.columns = columns.value;
|
|
variable.columns = columns.value;
|
|
- const values = command.initial.map((rows) =>
|
|
|
|
- rows.map((exp) => expressionWalker(exp).pop().value)
|
|
|
|
|
|
+ const values = command.initial.value.map((rows) =>
|
|
|
|
+ rows.value.map((exp) => variableInitialWalker(exp))
|
|
);
|
|
);
|
|
variable.value = values;
|
|
variable.value = values;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
// atomic
|
|
// atomic
|
|
variable.type = command.type.value;
|
|
variable.type = command.type.value;
|
|
- variable.value = expressionWalker(command.initial).pop().value;
|
|
|
|
|
|
+ variable.value = variableInitialWalker(command.initial);
|
|
}
|
|
}
|
|
return variable;
|
|
return variable;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @param {any} expression
|
|
|
|
+ * */
|
|
|
|
+function variableInitialWalker (expression) {
|
|
|
|
+ if (expression instanceof Expressions.UnaryApp) {
|
|
|
|
+ const left = variableInitialWalker(expression.left);
|
|
|
|
+ const opType = getOpType(expression.op);
|
|
|
|
+ if (opType !== TYPES.ARITHMETIC) {
|
|
|
|
+ throw new Error(
|
|
|
|
+ "invalid variable initial value: " + expression.toString()
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ return `${expression.op.value}${left}`;
|
|
|
|
+ } else if (expression instanceof Expressions.BoolLiteral) {
|
|
|
|
+ const value = expression.value;
|
|
|
|
+ return convertBoolToString(value);
|
|
|
|
+ } else if (expression instanceof Literal) {
|
|
|
|
+ let value = expression.value;
|
|
|
|
+ if (expression.value.toNumber) {
|
|
|
|
+ if (
|
|
|
|
+ Types.REAL.isCompatible(expression.type) &&
|
|
|
|
+ expression.value.decimalPlaces() == 0
|
|
|
|
+ ) {
|
|
|
|
+ value = expression.value.toFixed(2);
|
|
|
|
+ } else {
|
|
|
|
+ value = expression.value.toNumber();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return value;
|
|
|
|
+ }
|
|
|
|
+ throw new Error("invalid variable initial value: " + expression.toString());
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
*
|
|
*
|
|
* @return {[]}
|
|
* @return {[]}
|
|
@@ -273,6 +312,7 @@ function expressionWalker (expression) {
|
|
funcObj.params = paramsList;
|
|
funcObj.params = paramsList;
|
|
result = [funcObj];
|
|
result = [funcObj];
|
|
} else if (expression instanceof Expressions.UnaryApp) {
|
|
} else if (expression instanceof Expressions.UnaryApp) {
|
|
|
|
+ console.log(expression);
|
|
const left = expressionWalker(expression.left);
|
|
const left = expressionWalker(expression.left);
|
|
const opType = getOpType(expression.op);
|
|
const opType = getOpType(expression.op);
|
|
const opValue = translateOp(opType, expression.op);
|
|
const opValue = translateOp(opType, expression.op);
|
|
@@ -371,10 +411,14 @@ export function parseCode (text) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
parser.fill(tokenStream);
|
|
parser.fill(tokenStream);
|
|
- const program = parser.parseTree();
|
|
|
|
- const globals = program.global.map((decl) =>
|
|
|
|
- variableDeclarationWalker(decl, true)
|
|
|
|
- );
|
|
|
|
- const functions = program.functions.map(functionWalker);
|
|
|
|
- return { globals, functions };
|
|
|
|
|
|
+ try {
|
|
|
|
+ const program = parser.parseTree();
|
|
|
|
+ const globals = program.global.map((decl) =>
|
|
|
|
+ variableDeclarationWalker(decl, true)
|
|
|
|
+ );
|
|
|
|
+ const functions = program.functions.map(functionWalker);
|
|
|
|
+ return { globals, functions };
|
|
|
|
+ } catch {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
}
|
|
}
|