keean/zenscript

generate assembler code for higher-order functions

Opened this issue · 1 comments

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>();

}

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

  • PARSER RULES
    ------------------------------------------------------------------/

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));
}
} ;

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

  • LEXER RULES
    ------------------------------------------------------------------/

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.

binary inside the parenthesis