Forráskód Böngészése

Implement new for execution

Fix some syntatic and semantic bugs regarding the new for structure
Lucas de Souza 4 éve
szülő
commit
cebbbfabef

+ 34 - 55
js/ast/ivprogParser.js

@@ -893,10 +893,15 @@ export class IVProgParser {
     this.pushScope(IVProgParser.BREAKABLE);
     const for_token = this.getToken();
     this.pos += 1;
-    const for_id = this.parseID();
-    const for_from = this.parseForFrom();
-    const for_to = this.parseForTo();
-    let maybePass = this.parseForPass();
+    // parse ID
+    const id_token = this.getToken();
+    const id = this.parseID();
+    const for_id = new Expressions.VariableLiteral(id);
+    for_id.sourceInfo = SourceInfo.createSourceInfo(id_token);
+    // END parse ID
+    const for_from = this.parseForParameters(this.lexerClass.RK_FOR_FROM);
+    const for_to = this.parseForParameters(this.lexerClass.RK_FOR_TO);
+    let maybePass = this.parseForParameters(this.lexerClass.RK_FOR_PASS);
     this.consumeNewLines();
     const commandsBlock = this.parseCommandBlock();
     this.popScope();
@@ -996,71 +1001,45 @@ export class IVProgParser {
     }
   }
 
-  parseForFrom () {
-    const from_token = this.getToken();
-    if (from_token.type !== this.lexerClass.RK_FOR_FROM) {
-      // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_FROM];
-      throw new Error("Error de sintaxe no comando repita_para: esperava-se "+keyword+" mas encontrou "+from_token.text);
-    }
-    this.pos += 1;
-    const int_or_id = this.getToken();
-    if (int_or_id.type === this.lexerClass.ID) {
-      return this.parseID();
-    } else if (int_or_id.type === this.lexerClass.INTEGER) {
-      this.pos += 1;
-      return this.getIntLiteral(int_or_id);
-    } else {
-      // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_FROM];      
-      throw new Error("Error de sintaxe no comando repeita_para: "+ int_or_id.text + " não é compativel com o esperado para o paramentro "+ keyword + ". O valor deve ser um inteiro ou variável.");
+  parseForParameters (keyword_code) {
+    if(keyword_code === this.lexerClass.RK_FOR_PASS) {
+      if(this.checkOpenCurly(true)) {
+        return null;
+      }
     }
-  }
-
-  parseForTo () {
     const from_token = this.getToken();
-    if (from_token.type !== this.lexerClass.RK_FOR_TO) {
+    if (from_token.type !== keyword_code) {
       // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_TO];
+      const keyword = this.lexer.literalNames[keyword_code];
       throw new Error("Error de sintaxe no comando repita_para: esperava-se "+keyword+" mas encontrou "+from_token.text);
     }
     this.pos += 1;
-    const int_or_id = this.getToken();
-    if (int_or_id.type === this.lexerClass.ID) {
-      return this.parseID();
-    } else if (int_or_id.type === this.lexerClass.INTEGER) {
+    let int_or_id = this.getToken();
+    let is_unary_op = false;
+    let op = null;
+    if(int_or_id.type === this.lexerClass.SUM_OP) {
+      is_unary_op = true;
+      op = int_or_id.text;
       this.pos += 1;
-      return this.getIntLiteral(int_or_id);
-    } else {
-      // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_TO];      
-      throw new Error("Error de sintaxe no comando repeita_para: "+ int_or_id.text + " não é compativel com o esperado para o paramentro "+ keyword + ". O valor deve ser um inteiro ou variável.");
-    }
-  }
-
-  parseForPass () {
-    this.consumeNewLines();
-    if(this.checkOpenCurly(true)) {
-      return null;
+      int_or_id = this.getToken();
     }
-    const from_token = this.getToken();
-    if (from_token.type !== this.lexerClass.RK_FOR_PASS) {
-      // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_TO];
-      throw new Error("Error de sintaxe no comando repita_para: esperava-se "+keyword+" mas encontrou "+from_token.text);
-    }
-    this.pos += 1;
-    const int_or_id = this.getToken();
+    let for_from = null;
     if (int_or_id.type === this.lexerClass.ID) {
-      return this.parseID();
+      for_from = new Expressions.VariableLiteral(this.parseID());
+      for_from.sourceInfo = SourceInfo.createSourceInfo(int_or_id);
     } else if (int_or_id.type === this.lexerClass.INTEGER) {
       this.pos += 1;
-      return this.getIntLiteral(int_or_id);
-    } else {
+      for_from = this.getIntLiteral(int_or_id);
+    }
+    if (for_from == null) {
       // TODO better error message
-      const keyword = this.lexer.literalNames[this.lexerClass.RK_FOR_PASS];      
+      const keyword = this.lexer.literalNames[keyword_code];      
       throw new Error("Error de sintaxe no comando repeita_para: "+ int_or_id.text + " não é compativel com o esperado para o paramentro "+ keyword + ". O valor deve ser um inteiro ou variável.");
     }
+    if (is_unary_op) {
+      for_from = new Expressions.UnaryApp(convertFromString(op), for_from);
+    }
+    return for_from;
   }
 
   parseCases () {

+ 31 - 9
js/processor/ivprogProcessor.js

@@ -13,7 +13,7 @@ import * as Expressions from './../ast/expressions/';
 import { StoreObjectArrayAddress } from './store/storeObjectArrayAddress';
 import { StoreObjectArrayAddressRef } from './store/storeObjectArrayAddressRef';
 import { ArrayType } from './../typeSystem/array_type';
-import { convertToString } from '../typeSystem/parsers';
+import { convertToString, toInt } from '../typeSystem/parsers';
 import { Config } from '../util/config';
 import Decimal from 'decimal.js';
 import { ProcessorErrorFactory } from './error/processorErrorFactory';
@@ -312,12 +312,36 @@ export class IVProgProcessor {
     });
   }
 
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Commands.For} cmd 
+   */
   executeFor (store, cmd) {
-    try {
-      //BEGIN for -> while rewrite
-      const initCmd = cmd.assignment;
-      const condition = cmd.condition;
-      const increment = cmd.increment;
+    //BEGIN for -> while rewrite
+    const initCmd = new Commands.Assign(cmd.for_id, cmd.for_from);
+    initCmd.sourceInfo = cmd.sourceInfo;
+    const is_forward_exp = new Expressions.InfixApp(Operators.GE, cmd.for_to, cmd.for_from);
+    return this.evaluateExpression(store, is_forward_exp).then (result => {
+      const is_forward = result.value;
+      let condition = null;
+      if (is_forward) {
+        condition = new Expressions.InfixApp(Operators.LE, cmd.for_id, cmd.for_to);
+      } else {
+        condition = new Expressions.InfixApp(Operators.GE, cmd.for_id, cmd.for_to);
+      }
+      condition.sourceInfo = cmd.sourceInfo;
+      let pass_value = cmd.for_pass;
+      if(pass_value == null) {
+        if(is_forward) {
+          pass_value = new Expressions.IntLiteral(toInt(1));
+        } else {
+          pass_value = new Expressions.IntLiteral(toInt(-1));
+        }
+      }
+      const increment = new Commands.Assign(cmd.for_id,
+        new Expressions.InfixApp(Operators.ADD, cmd.for_id, pass_value));
+        increment.sourceInfo = cmd.sourceInfo;
       const whileBlock = new Commands.CommandBlock([],
         cmd.commands.concat(increment));
       const forAsWhile = new Commands.While(condition, whileBlock);
@@ -325,9 +349,7 @@ export class IVProgProcessor {
       //END for -> while rewrite
       const newCmdList = [initCmd,forAsWhile];
       return this.executeCommands(store, newCmdList);
-    } catch (error) {
-      return Promise.reject(error);
-    }
+    }).catch(error => Promise.reject(error));
   }
 
   executeDoWhile (store, cmd) {

+ 7 - 4
js/processor/semantic/semanticAnalyser.js

@@ -322,6 +322,7 @@ export class SemanticAnalyser {
       this.checkCommands(type, cmd.commands, optional);
       return false;
     } else if (cmd instanceof For) {
+      console.log(cmd);
       const var_type = this.evaluateExpressionType(cmd.for_id);
       if (!var_type.isCompatible(Types.INTEGER)) {
         // TODO better error message
@@ -337,10 +338,12 @@ export class SemanticAnalyser {
         // TODO better error message
         throw new Error("o paramentro 'ate' do comando repita_para deve ser do tipo inteiro");
       }
-      const pass_type = this.evaluateExpressionType(cmd.for_pass);
-      if (!pass_type.isCompatible(Types.INTEGER)) {
-        // TODO better error message
-        throw new Error("o paramentro 'passo' do comando repita_para deve ser do tipo inteiro");
+      if (cmd.for_pass != null) {
+        const pass_type = this.evaluateExpressionType(cmd.for_pass);
+        if (!pass_type.isCompatible(Types.INTEGER)) {
+          // TODO better error message
+          throw new Error("o paramentro 'passo' do comando repita_para deve ser do tipo inteiro");
+        }
       }
       this.checkCommands(type, cmd.commands, optional);
       return false;