keean / zenscript

A trait based language that compiles to JavaScript
MIT License
42 stars 7 forks source link

generate assembler code for higher-order functions #47

Open LBacchiani opened 5 years ago

LBacchiani commented 5 years ago

I have to create a compilare for a fool Language where functions can be passed as parameters. I have these instructions to create assembler code:

`grammar SVM;

@header { import java.util.HashMap; }

@lexer::members { int lexicalErrors=0; }

@parser::members {

int[] code = new int[ExecuteVM.CODESIZE];    
private int i = 0;
private HashMap<String,Integer> labelAdd = new HashMap<String,Integer>();
private HashMap<Integer,String> labelRef = new HashMap<Integer,String>();

}

/*------------------------------------------------------------------

assembly: ( PUSH n=NUMBER {code[i++] = PUSH; code[i++] = Integer.parseInt($n.text);} | PUSH l=LABEL {code[i++] = PUSH; // labelRef.put(i++,$l.text);}
| POP {code[i++] = POP;}
| ADD {code[i++] = ADD;} | SUB {code[i++] = SUB;} | MULT {code[i++] = MULT;} | DIV {code[i++] = DIV;} | STOREW {code[i++] = STOREW;} // | LOADW {code[i++] = LOADW;} // | l=LABEL COL {labelAdd.put($l.text,i);} | BRANCH l=LABEL {code[i++] = BRANCH; labelRef.put(i++,$l.text);} | BRANCHEQ l=LABEL {code[i++] = BRANCHEQ; // labelRef.put(i++,$l.text);} | BRANCHLESSEQ l=LABEL {code[i++] = BRANCHLESSEQ; labelRef.put(i++,$l.text);} | JS {code[i++] = JS;} // | LOADRA {code[i++] = LOADRA;} // | STORERA {code[i++] = STORERA;} // | LOADRV {code[i++] = LOADRV;} // | STORERV {code[i++] = STORERV;} // | LOADFP {code[i++] = LOADFP;} // | STOREFP {code[i++] = STOREFP;} // | COPYFP {code[i++] = COPYFP;} // | LOADHP {code[i++] = LOADHP;} // | STOREHP {code[i++] = STOREHP;} // | PRINT {code[i++] = PRINT;} | HALT {code[i++] = HALT;} )* { for (Integer refAdd: labelRef.keySet()) { code[refAdd]=labelAdd.get(labelRef.get(refAdd)); } } ;

/*------------------------------------------------------------------

PUSH : 'push' ;
POP : 'pop' ;
ADD : 'add' ;
SUB : 'sub' ;
MULT : 'mult' ;
DIV : 'div' ;
STOREW : 'sw' ;
LOADW : 'lw' ;
BRANCH : 'b' ;
BRANCHEQ : 'beq' ;
BRANCHLESSEQ:'bleq' ;
JS : 'js' ;
LOADRA : 'lra' ;
STORERA : 'sra' ;
LOADRV : 'lrv' ;
STORERV : 'srv' ;
LOADFP : 'lfp' ;
STOREFP : 'sfp' ;
COPYFP : 'cfp' ;
LOADHP : 'lhp' ;
STOREHP : 'shp' ;
PRINT : 'print' ;
HALT : 'halt' ;

COL : ':' ; LABEL : ('a'..'z'|'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'9') ; NUMBER : '0' | ('-')?(('1'..'9')('0'..'9')) ;

WHITESP : (' '|'\t'|'\n'|'\r')+ -> channel(HIDDEN) ;

ERR : . { System.out.println("Invalid char: "+ getText()); lexicalErrors++; } -> channel(HIDDEN); `

I have to generate the code for this small program:

` let

 fun g:int(x:(int,int)->int)
       x(5,7);
 fun f:int(c:int)
       let
             fun linsum:int(a:int,b:int)
            (a+b)*c;
      in 
           g(linsum);  

in print(f(5)); ` I have generated this code but the result isn'correct:

`push 0 push function0 push function2 lfp push 5 lfp push -3 lfp add lw js print halt

function0: cfp lra lfp push 7 push 5 lfp push 2 lfp add lw js srv sra pop pop pop sfp lrv lra js

function1: cfp lra push 1 lfp add lw push 2 lfp add lw add push 1 lfp lw add lw mult srv sra pop pop pop sfp lrv lra js

function2: cfp lra push function1 lfp push -2 lfp add lw push -4 lfp add lw lfp lw push -2 lfp lw add lw js srv pop sra pop pop sfp lrv lra js ` but the result is 420 and i have to get 60. I have found the error into three nodes: funNode's code generation, callNode's code generation and idNode's code generation: funNode:

` public String codeGeneration() { String declCode=""; for (Node dec:declist) declCode+=dec.codeGeneration();

    String popDecl="";
    for (DecNode dec:declist.stream().map(x->(DecNode)x).collect(Collectors.toList())) {
        if (dec.getSymType() instanceof ArrowTypeNode) {
            popDecl+="pop\n";       
        }
        popDecl+="pop\n";       
    }

    String popParl="";
    for (DecNode par:parlist.stream().map(x->(DecNode)x).collect(Collectors.toList())) 
    {
        if (par.getSymType() instanceof ArrowTypeNode) {
            popParl+="pop\n";
        }
        popParl+="pop\n";
    }

    String funl=FOOLlib.freshFunLabel();

      FOOLlib.putCode(funl+":\n"+
              "cfp\n"+
              "lra\n"+ 
              declCode+ 
              exp.codeGeneration()+
              "srv\n"+ 
              popDecl+
              "sra\n"+    
              "pop\n"+ 
              popParl+
              "sfp\n"+ 
              "lrv\n"+  
              "lra\n"+
              "js\n" 
              );

      return  
              "push "+ funl + "\n";
}`

CallNode:

return "lfp \n"+ parCode+ "lfp\n"+getAR+ "push "+entry.getOffset()+"\n"+ "lfp\n"+getAR+ "add\n"+ "lw\n"+ "js\n"; id Node:

`

                            return 
                                    "push "+(entry.getOffset())+"\n"+            
                "lfp\n"+getAR+ 
                "add\n"+       
                "lw\n";

`

but I don't know how to fix them.

pastafood10 commented 5 years ago

binary inside the parenthesis