|
@@ -18,6 +18,8 @@ import { Config } from '../util/config';
|
|
|
import Decimal from 'decimal.js';
|
|
|
import { ProcessorErrorFactory } from './error/processorErrorFactory';
|
|
|
import { RuntimeError } from './error/runtimeError';
|
|
|
+import { Type } from '../typeSystem/type';
|
|
|
+import { Literal } from '../ast/expressions/literal';
|
|
|
|
|
|
export class IVProgProcessor {
|
|
|
|
|
@@ -517,6 +519,7 @@ export class IVProgProcessor {
|
|
|
column = columnSO.number;
|
|
|
}
|
|
|
const value = this.parseStoreObjectValue(results[2]);
|
|
|
+ let actualValue = value;
|
|
|
if (line >= mustBeArray.lines) {
|
|
|
if(mustBeArray.isVector) {
|
|
|
return Promise.reject(ProcessorErrorFactory.vector_line_outbounds_full(cmd.id, line, mustBeArray.lines, cmd.sourceInfo));
|
|
@@ -539,33 +542,49 @@ export class IVProgProcessor {
|
|
|
|
|
|
const newArray = Object.assign(new StoreObjectArray(null,null,null), mustBeArray);
|
|
|
if (column !== null) {
|
|
|
- if (value.type instanceof ArrayType || !newArray.type.canAccept(value.type)) {
|
|
|
- const type = mustBeArray.type.innerType;
|
|
|
- const stringInfo = type.stringInfo()
|
|
|
- const info = stringInfo[0]
|
|
|
- return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
|
|
|
+ if (!newArray.type.canAccept(value.type)) {
|
|
|
+ if(!Config.enable_type_casting || !Store.canImplicitTypeCast(mustBeArray.type.innerType, value.type)) {
|
|
|
+ const type = mustBeArray.type.innerType;
|
|
|
+ const stringInfo = type.stringInfo();
|
|
|
+ const info = stringInfo[0];
|
|
|
+ const exp = cmd.expression.toString();
|
|
|
+ return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
|
|
|
+ }
|
|
|
+ actualValue = Store.doImplicitCasting(mustBeArray.type.innerType, value);
|
|
|
}
|
|
|
- newArray.value[line].value[column] = value;
|
|
|
+ newArray.value[line].value[column] = actualValue;
|
|
|
store.updateStore(cmd.id, newArray);
|
|
|
} else {
|
|
|
- if((mustBeArray.columns !== null && value.type instanceof ArrayType) || !newArray.type.canAccept(value.type)) {
|
|
|
- const type = mustBeArray.type;
|
|
|
- const stringInfo = type.stringInfo()
|
|
|
- const info = stringInfo[0]
|
|
|
- const exp = cmd.expression.toString()
|
|
|
- return Promise.reject(ProcessorErrorFactory.incompatible_types_array_full(exp,info.type, info.dim-1, cmd.sourceInfo));
|
|
|
+ if(!newArray.type.canAccept(value.type)) {
|
|
|
+ if(!Config.enable_type_casting || !Store.canImplicitTypeCast(mustBeArray.type.innerType, value.type)) {
|
|
|
+ const type = mustBeArray.type;
|
|
|
+ const stringInfo = type.stringInfo();
|
|
|
+ const info = stringInfo[0];
|
|
|
+ const exp = cmd.expression.toString();
|
|
|
+ return Promise.reject(ProcessorErrorFactory.incompatible_types_array_full(exp,info.type, info.dim-1, cmd.sourceInfo));
|
|
|
+ }
|
|
|
+ actualValue = Store.doImplicitCasting(mustBeArray.type.innerType, value);
|
|
|
}
|
|
|
- newArray.value[line] = value;
|
|
|
+ newArray.value[line] = actualValue;
|
|
|
store.updateStore(cmd.id, newArray);
|
|
|
}
|
|
|
return store;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Store} store
|
|
|
+ * @param {Commands.Declaration} cmd
|
|
|
+ */
|
|
|
executeDeclaration (store, cmd) {
|
|
|
try {
|
|
|
- const $value = this.evaluateExpression(store, cmd.initial);
|
|
|
+ let $value = Promise.resolve(null);
|
|
|
if(cmd instanceof Commands.ArrayDeclaration) {
|
|
|
+ if(cmd.initial !== null) {
|
|
|
+ // array can only be initialized by a literal....
|
|
|
+ $value = this.evaluateArrayLiteral(store, cmd.initial, cmd.type);
|
|
|
+ }
|
|
|
const $lines = this.evaluateExpression(store, cmd.lines);
|
|
|
const $columns = cmd.columns === null ? null: this.evaluateExpression(store, cmd.columns);
|
|
|
return Promise.all([$lines, $columns, $value]).then(values => {
|
|
@@ -614,6 +633,9 @@ export class IVProgProcessor {
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
+ if(cmd.initial !== null) {
|
|
|
+ $value = this.evaluateExpression(store, cmd.initial);
|
|
|
+ }
|
|
|
const temp = new StoreObject(cmd.type, null);
|
|
|
store.insertStore(cmd.id, temp);
|
|
|
return $value.then(vl => {
|
|
@@ -667,7 +689,7 @@ export class IVProgProcessor {
|
|
|
} else if (exp instanceof Expressions.StringLiteral) {
|
|
|
return this.evaluateLiteral(store, exp);
|
|
|
} else if (exp instanceof Expressions.ArrayLiteral) {
|
|
|
- return this.evaluateArrayLiteral(store, exp);
|
|
|
+ return Promise.reject(new Error("Internal Error: The system should not eval an array literal."))
|
|
|
} else if (exp instanceof Expressions.FunctionCall) {
|
|
|
return this.evaluateFunctionCall(store, exp);
|
|
|
}
|
|
@@ -696,13 +718,22 @@ export class IVProgProcessor {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- evaluateArrayLiteral (store, exp) {
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Store} store
|
|
|
+ * @param {Expressions.ArrayLiteral} exp
|
|
|
+ * @param {ArrayType} type
|
|
|
+ */
|
|
|
+ evaluateArrayLiteral (store, exp, type) {
|
|
|
const errorHelperFunction = (validationResult, exp) => {
|
|
|
const errorCode = validationResult[0];
|
|
|
+ let expectedColumns = null;
|
|
|
+ let actualColumns = null;
|
|
|
switch(errorCode) {
|
|
|
case StoreObjectArray.WRONG_COLUMN_NUMBER: {
|
|
|
- const columnValue = validationResult[1];
|
|
|
- return Promise.reject(ProcessorErrorFactory.invalid_array_literal_column_full(arr.columns, columnValue, exp.sourceInfo));
|
|
|
+ expectedColumns = validationResult[1];
|
|
|
+ actualColumns = validationResult[2];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_literal_column_full(expectedColumns, actualColumns, exp.sourceInfo));
|
|
|
}
|
|
|
case StoreObjectArray.WRONG_LINE_NUMBER: {
|
|
|
const lineValue = validationResult[1];
|
|
@@ -719,13 +750,13 @@ export class IVProgProcessor {
|
|
|
line = validationResult[1];
|
|
|
strExp = exp.value[line].toString()
|
|
|
}
|
|
|
+ // TODO - fix error message
|
|
|
return Promise.reject(ProcessorErrorFactory.invalid_array_literal_type_full(strExp, exp.sourceInfo)); }
|
|
|
}
|
|
|
};
|
|
|
if(!exp.isVector) {
|
|
|
- const $matrix = this.evaluateMatrix(store, exp.value);
|
|
|
+ const $matrix = this.evaluateMatrix(store, exp.value, type);
|
|
|
return $matrix.then(list => {
|
|
|
- const type = new ArrayType(list[0].type.innerType, 2);
|
|
|
const arr = new StoreObjectArray(type, list.length, list[0].lines, list);
|
|
|
const checkResult = arr.isValid;
|
|
|
if(checkResult.length == 0)
|
|
@@ -735,7 +766,7 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
|
- return this.evaluateVector(store, exp.value).then(list => {
|
|
|
+ return this.evaluateVector(store, exp.value, type).then(list => {
|
|
|
const type = new ArrayType(list[0].type, 1);
|
|
|
const stoArray = new StoreObjectArray(type, list.length, null, list);
|
|
|
const checkResult = stoArray.isValid;
|
|
@@ -748,16 +779,45 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- evaluateVector (store, exps) {
|
|
|
- return Promise.all(exps.map( exp => this.evaluateExpression(store, exp)));
|
|
|
+ /**
|
|
|
+ * Evalautes a list of literals and expression composing the vector
|
|
|
+ * @param {Store} store
|
|
|
+ * @param {Literal[]} exps
|
|
|
+ * @param {ArrayType} type
|
|
|
+ * @returns {Promise<StoreObject[]>} store object list
|
|
|
+ */
|
|
|
+ evaluateVector (store, exps, type) {
|
|
|
+ const actual_values = Promise.all(exps.map( exp => this.evaluateExpression(store, exp)));
|
|
|
+ return actual_values.then( values => {
|
|
|
+ return values.map((v, index) => {
|
|
|
+ if(!type.canAccept(v.type)) {
|
|
|
+ if (!Config.enable_type_casting || !Store.canImplicitTypeCast(type.innerType, v.type)) {
|
|
|
+ const stringInfo = v.type.stringInfo();
|
|
|
+ const info = stringInfo[0];
|
|
|
+ const exp_str = exps[index].toString();
|
|
|
+ // TODO - fix error message
|
|
|
+ throw ProcessorErrorFactory.invalid_array_literal_type_full(exp_str, exps[index].sourceInfo);
|
|
|
+ }
|
|
|
+ const new_value = Store.doImplicitCasting(type.innerType, v);
|
|
|
+ return new_value;
|
|
|
+ }
|
|
|
+ return v;
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- evaluateMatrix (store, exps) {
|
|
|
+ /**
|
|
|
+ * Evaluates a list of array literals composing the matrix
|
|
|
+ * @param {Store} store
|
|
|
+ * @param {Expressions.ArrayLiteral[]} exps
|
|
|
+ * @param {ArrayType} type
|
|
|
+ */
|
|
|
+ evaluateMatrix (store, exps, type) {
|
|
|
return Promise.all(exps.map( vector => {
|
|
|
- const $vector = this.evaluateVector(store, vector.value)
|
|
|
+ const vec_type = new ArrayType(type.innerType, 1);
|
|
|
+ const $vector = this.evaluateVector(store, vector.value, vec_type);
|
|
|
return $vector.then(list => {
|
|
|
- const type = new ArrayType(list[0].type, 1);
|
|
|
- return new StoreObjectArray(type, list.length, null, list)
|
|
|
+ return new StoreObjectArray(vec_type, list.length, null, list)
|
|
|
});
|
|
|
} ));
|
|
|
}
|