Kaynağa Gözat

Fix const variable being passed as reference

Fix some parameters association error messages
Lucas de Souza 5 yıl önce
ebeveyn
işleme
28e793016b

+ 3 - 1
i18n/pt/error.json

@@ -95,5 +95,7 @@
   "inform_valid_variable_duplicated" : "Já existe uma variável com o nome <span class='ivprog-error-varname'>$0</span> na função <span class='ivprog-error-varname'>$1</span>, você precisa de nomes distintos.",
   "inform_valid_function_duplicated" : "Já existe uma função com o nome <span class='ivprog-error-varname'>$0</span>, você precisa de nomes distintos.",
   "inform_valid_param_duplicated" : "Já existe um parâmetro com o nome <span class='ivprog-error-varname'>$0</span> na função <span class='ivprog-error-varname'>$1</span>, você precisa de nomes distintos.",
-  "invalid_character": "O caractere $0 na linha $1 não pode ser utilizado neste contexto."
+  "invalid_character": "O caractere $0 na linha $1 não pode ser utilizado neste contexto.",
+  "invalid_const_ref_full": "A variável $0 fornecida como parâmetro para a função $1 na linha $2 é uma constante e não pode ser usada neste contexto. Use uma variável ou posição de vetor.",
+  "invalid_const_ref": "A variável $0 fornecida como parâmetro para a função $1 é uma constante e não pode ser usada neste contexto. Use uma variável ou posição de vetor."
 }

+ 2 - 2
js/processor/definedFunctions.js

@@ -18,7 +18,7 @@ import {createAbsFun, createCosFun,
 
 function valueToKey (value, object) {
   for (const key in object) {
-    if(object.hasOwnProperty(key)){
+    if(Object.prototype.hasOwnProperty.call(object, key)){
       if (object[key] === value) {
         return key;
       }
@@ -32,7 +32,7 @@ function concatObjects (...objs) {
   for (let i = 0; i < objs.length; i++) {
     const obj = objs[i];
     for(const key in obj) {
-      if(obj.hasOwnProperty(key)) {
+      if(Object.prototype.hasOwnProperty.call(obj, key)) {
         result[key] = obj[key];
       }
     }

+ 18 - 5
js/processor/error/processorErrorFactory.js

@@ -1,6 +1,7 @@
 import { RuntimeError } from './runtimeError';
 import { SemanticError } from './semanticError';
 import * as  LocalizedStringsService from './../../services/localizedStringsService';
+import { LanguageDefinedFunction } from '../definedFunctions';
 
 const LocalizedStrings = LocalizedStringsService.getInstance();
 
@@ -269,16 +270,16 @@ export const ProcessorErrorFactory  = Object.freeze({
     const context = [id, expected, actual];
     return new SemanticError(LocalizedStrings.getError("invalid_parameters_size", context));
   },
-  invalid_parameter_type_full: (id, exp, sourceInfo) => {
+  invalid_parameter_type_full: (fun_name, exp, sourceInfo) => {
     if(sourceInfo) {
-      const context = [exp, id, sourceInfo.line];
+      const context = [exp, LanguageDefinedFunction.getLocalName(fun_name), sourceInfo.line];
       return new SemanticError(LocalizedStrings.getError("invalid_parameter_type_full", context));
     } else {
-      return ProcessorErrorFactory.invalid_parameter_type(id, exp);
+      return ProcessorErrorFactory.invalid_parameter_type(fun_name, exp);
     }
   },
-  invalid_parameter_type: (id, exp) => {
-    const context = [exp, id];
+  invalid_parameter_type: (fun_name, exp) => {
+    const context = [exp, LanguageDefinedFunction.getLocalName(fun_name)];
     return new SemanticError(LocalizedStrings.getError("invalid_parameter_type_full", context));
   },
   invalid_ref_full: (id, exp, sourceInfo) => {
@@ -386,5 +387,17 @@ export const ProcessorErrorFactory  = Object.freeze({
   invalid_read_type_array: (exp, typePos, dimPos, name, typeArray, dimArray) => {
     const context = [exp, LocalizedStrings.translateType(typePos, dimPos), name,LocalizedStrings.translateType(typeArray, dimArray)];
     return new RuntimeError(LocalizedStrings.getError("invalid_read_type_array", context))
+  },
+  invalid_const_ref_full: (fun_name, exp, sourceInfo)=> {
+    if(sourceInfo) {
+      const context = [exp, LanguageDefinedFunction.getLocalName(fun_name), sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("invalid_const_ref_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_const_ref(fun_name, exp);
+    }
+  },
+  invalid_const_ref: (fun_name, exp) => {
+    const context = [exp, LanguageDefinedFunction.getLocalName(fun_name)];
+    return new SemanticError(LocalizedStrings.getError("invalid_const_ref", context));
   }
 });

+ 19 - 14
js/processor/semantic/semanticAnalyser.js

@@ -66,13 +66,13 @@ export class SemanticAnalyser {
   findFunction (name) {
     if(name.match(/^\$.+$/)) {
       const fun = LanguageDefinedFunction.getFunction(name);
-      if(!!!fun) {
+      if(!fun) {
         throw ProcessorErrorFactory.not_implemented(name);
       }
       return fun;
     } else {
       const val = this.ast.functions.find( v => v.name === name);
-      if (!!!val) {
+      if (!val) {
         return null;
       }
       return val;
@@ -114,15 +114,15 @@ export class SemanticAnalyser {
             throw ProcessorErrorFactory.array_dimension_not_int_full(declaration.sourceInfo);
           }
         }
-        this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type});
+        this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type, isConst: declaration.isConst});
         return;
       }
       this.evaluateArrayLiteral(declaration.id, declaration.lines, declaration.columns, declaration.type, declaration.initial);
-      this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type});
+      this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type, isConst: declaration.isConst});
 
     } else {
       if(declaration.initial === null) {
-        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type});
+        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type, isConst: declaration.isConst});
         return;
       }
       const resultType = this.evaluateExpressionType(declaration.initial);
@@ -132,7 +132,7 @@ export class SemanticAnalyser {
           const info = stringInfo[0];
           throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, declaration.sourceInfo);
         }
-        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type})
+        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type, isConst: declaration.isConst})
       } else if((!declaration.type.isCompatible(resultType) && !Config.enable_type_casting)
         || (!declaration.type.isCompatible(resultType) && Config.enable_type_casting
         && !Store.canImplicitTypeCast(declaration.type, resultType))) {
@@ -140,7 +140,7 @@ export class SemanticAnalyser {
         const info = stringInfo[0];
         throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, declaration.sourceInfo);
       } else {
-        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type});
+        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type, isConst: declaration.isConst});
       }
     }
   }
@@ -264,7 +264,7 @@ export class SemanticAnalyser {
     }
   }
 
-  evaluateArrayLiteral (id, lines, columns, type, literal) {
+  evaluateArrayLiteral (/*id, lines, columns, type, literal*/) {
     /* if (literal instanceof ArrayLiteral) {
       const dimType = this.evaluateExpressionType(lines);
       if (!dimType.isCompatible(Types.INTEGER)) {
@@ -519,10 +519,15 @@ export class SemanticAnalyser {
     for (let i = 0; i < actualParametersList.length; ++i) {
       const param = actualParametersList[i];
       const formalParam = fun.formalParameters[i];
-      const id = formalParam.id;
+      // const id = formalParam.id;
       if(formalParam.byRef) {
-        if (!(param instanceof VariableLiteral || param instanceof ArrayAccess)) {
-          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
+        if(param instanceof VariableLiteral) {
+          const variable = this.findSymbol(param.id, this.symbolMap);
+          if (variable.isConst) {
+            throw ProcessorErrorFactory.invalid_const_ref_full(fun.name, param.toString(), param.sourceInfo);  
+          }
+        } else if (!(param instanceof VariableLiteral || param instanceof ArrayAccess)) {
+          throw ProcessorErrorFactory.invalid_parameter_type_full(fun.name, param.toString(), param.sourceInfo);
         }
       }
       const resultType = this.evaluateExpressionType(param);
@@ -542,7 +547,7 @@ export class SemanticAnalyser {
               }
             }
           }
-          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
+          throw ProcessorErrorFactory.invalid_parameter_type_full(fun.name, param.toString(), param.sourceInfo);
         }
       } else if (resultType instanceof MultiType) {
         if(!resultType.isCompatible(formalParam.type)) {
@@ -553,7 +558,7 @@ export class SemanticAnalyser {
               }
             }
           }
-          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
+          throw ProcessorErrorFactory.invalid_parameter_type_full(fun.name, param.toString(), param.sourceInfo);
         }
       } else if(!formalParam.type.isCompatible(resultType)) {
         if(Config.enable_type_casting && !formalParam.byRef) {
@@ -561,7 +566,7 @@ export class SemanticAnalyser {
             continue;
           }
         }
-        throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
+        throw ProcessorErrorFactory.invalid_parameter_type_full(fun.name, param.toString(), param.sourceInfo);
       }
 
     }