├── test ├── a.spl ├── b.spl ├── tailcall.spl ├── rec.spl ├── c.spl ├── if.spl ├── func.spl └── array.spl ├── old ├── compiler_minimal │ ├── a.spl │ ├── readme.txt │ ├── a.spl2 │ ├── b.spl │ ├── b.spl2 │ └── compiler.py └── compiler_backend │ ├── test │ ├── a.spl │ ├── a.spl2 │ ├── b.spl │ ├── c.spl │ ├── if.spl │ ├── func.spl │ ├── array.spl │ ├── b.spl2 │ ├── c.spl2 │ ├── rec.spl2 │ ├── tailcall.spl2 │ ├── if.spl2 │ ├── func.spl2 │ └── array.spl2 │ ├── readme.txt │ ├── runtest.sh │ └── compiler.py ├── debug.py ├── compiler.py ├── runtest.sh ├── ast_generator.py ├── slr_parser.py ├── grammar.py ├── README.md ├── parser_generator.py └── asm_generator.py /test/a.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | a = 6; 4 | iprint(a); 5 | } 6 | -------------------------------------------------------------------------------- /old/compiler_minimal/a.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | a = 6; 4 | iprint(a); 5 | } 6 | -------------------------------------------------------------------------------- /old/compiler_backend/test/a.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | a = 6; 4 | iprint(a); 5 | } 6 | -------------------------------------------------------------------------------- /old/compiler_backend/readme.txt: -------------------------------------------------------------------------------- 1 | Compile like this: 2 | 3 | python compiler.py a.spl2 > a.s 4 | 5 | -------------------------------------------------------------------------------- /old/compiler_minimal/readme.txt: -------------------------------------------------------------------------------- 1 | Compile like this: 2 | 3 | python compiler.py a.spl2 > a.s 4 | 5 | -------------------------------------------------------------------------------- /old/compiler_minimal/a.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a))) 4 | (STMTS 5 | (ASSIGN (VAR a) (INTEXP 6)) 6 | (CALLPROC iprint (VAREXP (VAR a)))) 7 | ) 8 | -------------------------------------------------------------------------------- /old/compiler_backend/test/a.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a))) 4 | (STMTS 5 | (ASSIGN (VAR a) (INTEXP 6)) 6 | (CALLPROC iprint (VAREXP (VAR a)))) 7 | ) 8 | -------------------------------------------------------------------------------- /test/b.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 7; 5 | b = 3; 6 | iprint(a+1); 7 | iprint(b+1); 8 | iprint(a+b); 9 | iprint(a-b); 10 | iprint(a*b); 11 | iprint(a/b); 12 | } 13 | -------------------------------------------------------------------------------- /old/compiler_minimal/b.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 7; 5 | b = 3; 6 | iprint(a+1); 7 | iprint(b+1); 8 | iprint(a+b); 9 | iprint(a-b); 10 | iprint(a*b); 11 | iprint(a/b); 12 | } 13 | -------------------------------------------------------------------------------- /old/compiler_backend/test/b.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 7; 5 | b = 3; 6 | iprint(a+1); 7 | iprint(b+1); 8 | iprint(a+b); 9 | iprint(a-b); 10 | iprint(a*b); 11 | iprint(a/b); 12 | } 13 | -------------------------------------------------------------------------------- /test/tailcall.spl: -------------------------------------------------------------------------------- 1 | { 2 | int f(int n, int acc){ 3 | if(n==0) 4 | return acc; 5 | else 6 | tailcall f(n-1, n+acc); 7 | end 8 | } 9 | iprint(f(1000000)); 10 | } 11 | -------------------------------------------------------------------------------- /test/rec.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int f(int n){ 4 | if(n<1) 5 | return 1; 6 | else 7 | return n * f(n-1); 8 | end 9 | } 10 | a = f(5); 11 | iprint(a); 12 | } 13 | -------------------------------------------------------------------------------- /test/c.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 111; 5 | b = 123; 6 | iprint(a); 7 | iprint(b); 8 | { 9 | int a; 10 | a = 777; 11 | iprint(a); 12 | iprint(b); 13 | } 14 | iprint(a); 15 | iprint(b); 16 | } 17 | -------------------------------------------------------------------------------- /old/compiler_backend/test/c.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 111; 5 | b = 123; 6 | iprint(a); 7 | iprint(b); 8 | { 9 | int a; 10 | a = 777; 11 | iprint(a); 12 | iprint(b); 13 | } 14 | iprint(a); 15 | iprint(b); 16 | } 17 | -------------------------------------------------------------------------------- /test/if.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 7; 5 | b = 1; 6 | if(a!=5){ 7 | iprint(1); 8 | if(a<=5){ 9 | iprint(0); 10 | }else{ 11 | iprint(2); 12 | }end 13 | }end 14 | while(b<10){ 15 | iprint(b); 16 | b = b+1; 17 | }end 18 | } 19 | -------------------------------------------------------------------------------- /old/compiler_backend/test/if.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a; 3 | int b; 4 | a = 7; 5 | b = 1; 6 | if(a!=5){ 7 | iprint(1); 8 | if(a<=5){ 9 | iprint(0); 10 | }else{ 11 | iprint(2); 12 | } 13 | } 14 | while(b<10){ 15 | iprint(b); 16 | b = b+1; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/func.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a[3]; 3 | int b; 4 | int f(int x, int y){ 5 | int z; 6 | z = x * y; 7 | a[1] = 777; 8 | iprint(a[1]); 9 | iprint(z); 10 | return z; 11 | iprint(z); 12 | } 13 | int g(){ 14 | iprint(999); 15 | } 16 | b = f(111, 3); 17 | g(); 18 | iprint(b); 19 | iprint(a[1]); 20 | } 21 | -------------------------------------------------------------------------------- /old/compiler_backend/test/func.spl: -------------------------------------------------------------------------------- 1 | { 2 | int[3] a; 3 | int b; 4 | int f(int x, int y){ 5 | int z; 6 | z = x * y; 7 | a[1] = 777; 8 | iprint(a[1]); 9 | iprint(z); 10 | return z; 11 | iprint(z); 12 | } 13 | int g(){ 14 | iprint(999); 15 | } 16 | b = f(111, 3); 17 | g(); 18 | iprint(b); 19 | iprint(a[1]); 20 | } 21 | -------------------------------------------------------------------------------- /test/array.spl: -------------------------------------------------------------------------------- 1 | { 2 | int a[3]; 3 | int b; 4 | a[0] = 1; 5 | a[1] = 2; 6 | a[2] = 3; 7 | b = 777; 8 | iprint(a[0]); 9 | iprint(a[1]); 10 | iprint(a[2]); 11 | iprint(b); 12 | { 13 | int a[3]; 14 | a[0] = 4; 15 | a[1] = 5; 16 | a[2] = 6; 17 | iprint(a[0]); 18 | iprint(a[1]); 19 | iprint(a[2]); 20 | iprint(b); 21 | } 22 | iprint(a[0]); 23 | iprint(a[1]); 24 | iprint(a[2]); 25 | iprint(b); 26 | } 27 | -------------------------------------------------------------------------------- /old/compiler_backend/test/array.spl: -------------------------------------------------------------------------------- 1 | { 2 | int[3] a; 3 | int b; 4 | a[0] = 1; 5 | a[1] = 2; 6 | a[2] = 3; 7 | b = 777; 8 | iprint(a[0]); 9 | iprint(a[1]); 10 | iprint(a[2]); 11 | iprint(b); 12 | { 13 | int[3] a; 14 | a[0] = 4; 15 | a[1] = 5; 16 | a[2] = 6; 17 | iprint(a[0]); 18 | iprint(a[1]); 19 | iprint(a[2]); 20 | iprint(b); 21 | } 22 | iprint(a[0]); 23 | iprint(a[1]); 24 | iprint(a[2]); 25 | iprint(b); 26 | } 27 | -------------------------------------------------------------------------------- /debug.py: -------------------------------------------------------------------------------- 1 | # For parsing a manually written AST. 2 | 3 | def tokenize(s): 4 | return s.replace("("," ( ").replace(")"," ) ").split() 5 | 6 | def parse(tokens): 7 | token = tokens.pop(0) 8 | if token == "(": 9 | L = [] 10 | while tokens[0] != ")": 11 | L.append(parse(tokens)) 12 | tokens.pop(0) 13 | return L 14 | elif token == ")": 15 | raise SyntaxError("unexpected )") 16 | else: 17 | return token 18 | 19 | -------------------------------------------------------------------------------- /compiler.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import slr_parser 3 | import asm_generator 4 | import ast_generator 5 | 6 | filename = sys.argv[1] 7 | with open(filename, "r") as f: 8 | code = f.read() 9 | 10 | tokens = slr_parser.tokenizer(code) 11 | parser_output = slr_parser.parser(tokens) 12 | ast = ast_generator.ast_generator(parser_output, tokens) 13 | code_asm = asm_generator.asm_generator(ast) 14 | 15 | with open("a.s", "w") as f: 16 | for i in code_asm: 17 | f.write(i+"\n") 18 | 19 | -------------------------------------------------------------------------------- /runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | runtest(){ 4 | python compiler.py "$1" 5 | gcc -o a.out a.s 6 | output=$(./a.out) 7 | if [ "$output" != "$2" ]; then 8 | echo "$1: $2 expected, but got $output" 9 | exit 1 10 | fi 11 | rm a.out a.s 12 | } 13 | 14 | runtest test/a.spl 6 15 | runtest test/b.spl 84104212 16 | runtest test/c.spl 111123777123111123 17 | runtest test/array.spl 123777456777123777 18 | runtest test/if.spl 12123456789 19 | runtest test/func.spl 777333999333777 20 | runtest test/rec.spl 120 21 | #runtest test/tailcall.spl 500000500000 22 | 23 | echo OK 24 | 25 | -------------------------------------------------------------------------------- /old/compiler_backend/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | runtest(){ 4 | python compiler.py "$1" > _tmp.s 5 | gcc -o _tmp _tmp.s 6 | output=$(./_tmp) 7 | if [ "$output" != "$2" ]; then 8 | echo "$1: $2 expected, but got $output" 9 | exit 1 10 | fi 11 | rm _tmp _tmp.s 12 | } 13 | 14 | runtest test/a.spl2 6 15 | runtest test/b.spl2 84104212 16 | runtest test/c.spl2 111123777123111123 17 | runtest test/array.spl2 123777456777123777 18 | runtest test/if.spl2 12123456789 19 | runtest test/func.spl2 777333999333777 20 | runtest test/rec.spl2 120 21 | runtest test/tailcall.spl2 500000500000 22 | 23 | echo OK 24 | 25 | -------------------------------------------------------------------------------- /old/compiler_minimal/b.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | ) 6 | (STMTS 7 | (ASSIGN (VAR a) (INTEXP 7)) 8 | (ASSIGN (VAR b) (INTEXP 3)) 9 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR a)) (INTEXP 1)))) 10 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR b)) (INTEXP 1)))) 11 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR a)) (VAREXP (VAR b))))) 12 | (CALLPROC iprint (CALLFUNC (- (VAREXP (VAR a)) (VAREXP (VAR b))))) 13 | (CALLPROC iprint (CALLFUNC (* (VAREXP (VAR a)) (VAREXP (VAR b))))) 14 | (CALLPROC iprint (CALLFUNC (/ (VAREXP (VAR a)) (VAREXP (VAR b))))) 15 | ) 16 | ) 17 | -------------------------------------------------------------------------------- /old/compiler_backend/test/b.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | ) 6 | (STMTS 7 | (ASSIGN (VAR a) (INTEXP 7)) 8 | (ASSIGN (VAR b) (INTEXP 3)) 9 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR a)) (INTEXP 1)))) 10 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR b)) (INTEXP 1)))) 11 | (CALLPROC iprint (CALLFUNC (+ (VAREXP (VAR a)) (VAREXP (VAR b))))) 12 | (CALLPROC iprint (CALLFUNC (- (VAREXP (VAR a)) (VAREXP (VAR b))))) 13 | (CALLPROC iprint (CALLFUNC (* (VAREXP (VAR a)) (VAREXP (VAR b))))) 14 | (CALLPROC iprint (CALLFUNC (/ (VAREXP (VAR a)) (VAREXP (VAR b))))) 15 | ) 16 | ) 17 | -------------------------------------------------------------------------------- /old/compiler_backend/test/c.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | ) 6 | (STMTS 7 | (ASSIGN (VAR a) (INTEXP 111)) 8 | (ASSIGN (VAR b) (INTEXP 123)) 9 | (CALLPROC iprint (VAREXP (VAR a))) 10 | (CALLPROC iprint (VAREXP (VAR b))) 11 | (BLOCK 12 | (DECS 13 | (VARDEC (INTTYP a)) 14 | ) 15 | (STMTS 16 | (ASSIGN (VAR a) (INTEXP 777)) 17 | (CALLPROC iprint (VAREXP (VAR a))) 18 | (CALLPROC iprint (VAREXP (VAR b))) 19 | ) 20 | ) 21 | (CALLPROC iprint (VAREXP (VAR a))) 22 | (CALLPROC iprint (VAREXP (VAR b))) 23 | ) 24 | ) 25 | -------------------------------------------------------------------------------- /old/compiler_backend/test/rec.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (FUNCDEC f 5 | ((INTTYP n)) 6 | INTTYP 7 | (IF (COND (< (VAREXP (VAR n)) (INTEXP 1))) 8 | (CALLPROC return (INTEXP 1)) 9 | ELSE 10 | (CALLPROC return 11 | (CALLFUNC (* (VAREXP (VAR n)) 12 | (CALLFUNC (f ((CALLFUNC (- (VAREXP (VAR n)) (INTEXP 1))))))))) 13 | ) 14 | ) 15 | ) 16 | (STMTS 17 | (ASSIGN (VAR a) (CALLFUNC (f ((INTEXP 5))))) 18 | (CALLPROC iprint (VAREXP (VAR a))) 19 | ) 20 | ) 21 | -------------------------------------------------------------------------------- /old/compiler_backend/test/tailcall.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (FUNCDEC f 5 | ((INTTYP n) 6 | (INTTYP acc)) 7 | INTTYP 8 | (BLOCK 9 | (DECS ) 10 | (STMTS 11 | (IF (COND (== (VAREXP (VAR n)) (INTEXP 0))) 12 | (CALLPROC return (VAREXP (VAR acc))) 13 | ) 14 | (CALLPROCTAIL f ((CALLFUNC (- (VAREXP (VAR n)) (INTEXP 1))) 15 | (CALLFUNC (+ (VAREXP (VAR n)) (VAREXP (VAR acc)))))) 16 | ) 17 | ) 18 | ) 19 | ) 20 | (STMTS 21 | (CALLPROC iprint (CALLFUNC (f ((INTEXP 1000000) (INTEXP 0))))) 22 | ) 23 | ) 24 | -------------------------------------------------------------------------------- /old/compiler_backend/test/if.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | ) 6 | (STMTS 7 | (ASSIGN (VAR a) (INTEXP 7)) 8 | (ASSIGN (VAR b) (INTEXP 1)) 9 | (IF 10 | (COND (!= (VAREXP (VAR a)) (INTEXP 5))) 11 | (BLOCK 12 | (DECS ) 13 | (STMTS 14 | (CALLPROC iprint (INTEXP 1)) 15 | (IF 16 | (COND (<= (VAREXP (VAR a)) (INTEXP 5))) 17 | (CALLPROC iprint (INTEXP 0)) 18 | ELSE 19 | (CALLPROC iprint (INTEXP 2)) 20 | ) 21 | ) 22 | ) 23 | ) 24 | (WHILE 25 | (COND (< (VAREXP (VAR b)) (INTEXP 10))) 26 | (BLOCK 27 | (DECS ) 28 | (STMTS 29 | (CALLPROC iprint (VAREXP (VAR b))) 30 | (ASSIGN (VAR b) (CALLFUNC (+ (VAREXP (VAR b)) (INTEXP 1)))) 31 | ) 32 | ) 33 | ) 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /old/compiler_backend/test/func.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (ARRAYTYP 3 INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | (FUNCDEC f 6 | ((INTTYP x) 7 | (INTTYP y)) 8 | INTTYP 9 | (BLOCK 10 | (DECS 11 | (VARDEC (INTTYP z)) 12 | ) 13 | (STMTS 14 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 1)) (INTEXP 777)) 15 | (ASSIGN (VAR z) (CALLFUNC (* (VAREXP (VAR x)) (VAREXP (VAR y))))) 16 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 17 | (CALLPROC iprint (VAREXP (VAR z))) 18 | (CALLPROC return (VAREXP (VAR z))) 19 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 20 | ) 21 | ) 22 | ) 23 | (FUNCDEC g 24 | () 25 | INTTYP 26 | (CALLPROC iprint (INTEXP 999)) 27 | ) 28 | ) 29 | (STMTS 30 | (ASSIGN (VAR b) (CALLFUNC (f ((INTEXP 111) (INTEXP 3))))) 31 | (CALLPROC g ()) 32 | (CALLPROC iprint (VAREXP (VAR b))) 33 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /old/compiler_backend/test/array.spl2: -------------------------------------------------------------------------------- 1 | (BLOCK 2 | (DECS 3 | (VARDEC (ARRAYTYP 3 INTTYP a)) 4 | (VARDEC (INTTYP b)) 5 | ) 6 | (STMTS 7 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 0)) (INTEXP 1)) 8 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 1)) (INTEXP 2)) 9 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 2)) (INTEXP 3)) 10 | (ASSIGN (VAR b) (INTEXP 777)) 11 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 0)))) 12 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 13 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 2)))) 14 | (CALLPROC iprint (VAREXP (VAR b))) 15 | (BLOCK 16 | (DECS 17 | (VARDEC (ARRAYTYP 3 INTTYP a)) 18 | ) 19 | (STMTS 20 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 0)) (INTEXP 4)) 21 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 1)) (INTEXP 5)) 22 | (ASSIGN (INDEXEDVAR (VAR a) (INTEXP 2)) (INTEXP 6)) 23 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 0)))) 24 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 25 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 2)))) 26 | (CALLPROC iprint (VAREXP (VAR b))) 27 | ) 28 | ) 29 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 0)))) 30 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 1)))) 31 | (CALLPROC iprint (VAREXP (INDEXEDVAR (VAR a) (INTEXP 2)))) 32 | (CALLPROC iprint (VAREXP (VAR b))) 33 | ) 34 | ) 35 | -------------------------------------------------------------------------------- /ast_generator.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from grammar import * 3 | import parser 4 | 5 | def ast_generator(parser_output, tokens): 6 | if parser_output == []: return 7 | r = parser_output.pop() 8 | if BNF[r][0] in ["_EXPR", "_TERM"]: 9 | if len(BNF[r][1]) == 1: 10 | return ast_generator(parser_output, tokens) 11 | else: 12 | parent = ["_CALLFUNC", BNF[r][1][1]] 13 | children = [ast_generator(parser_output, tokens)] 14 | children = [ast_generator(parser_output, tokens)] + children 15 | return parent + children 16 | elif BNF[r][0] == "_FACTOR": 17 | return ast_generator(parser_output, tokens) 18 | elif BNF[r][0] == "_COND": 19 | parent = ["_COND", BNF[r][1][1]] 20 | children = [ast_generator(parser_output, tokens)] 21 | children = [ast_generator(parser_output, tokens)] + children 22 | return parent + children 23 | else: 24 | parent = [BNF[r][0]] 25 | if BNF[r][0] == "_CALLPROC" and BNF[r][1][0] != "_FUNCNAME": 26 | parent += [BNF[r][1][0]] 27 | children = [] 28 | for i in BNF[r][1]: 29 | if i in ["_NUMBER", "_ALPHABET"]: 30 | identifier = tokens.pop() 31 | while identifier in TERMINAL: 32 | identifier = tokens.pop() 33 | children = [identifier] + children 34 | elif i in NONTERMINAL: 35 | children = [ast_generator(parser_output, tokens)] + children 36 | return parent + children 37 | 38 | 39 | -------------------------------------------------------------------------------- /slr_parser.py: -------------------------------------------------------------------------------- 1 | from grammar import * 2 | import parser_generator 3 | 4 | LR = parser_generator.parser_generator() 5 | r2n = [ i[0] for i in BNF ] 6 | pops = [ len(i[1]) for i in BNF] 7 | 8 | def tokenizer(code): 9 | punctuator = ["$", ";", ",", "+", "-", "*", "/", "(", ")", "{", "}", "[", "]", "=", ">", "<", "!"] 10 | for i in punctuator: 11 | code = code.replace(i," "+i+" ") 12 | for i in ["<=", ">=", "==", "!="]: 13 | code = code.replace(i[0]+" "+i[1], i) 14 | tokens = code.split() 15 | tokens += "$" 16 | return tokens 17 | 18 | def token_to_symbol(token): 19 | if token in SYMBOL: 20 | return token 21 | elif token.isdigit(): 22 | return "_NUMBER" 23 | else: 24 | return "_ALPHABET" 25 | 26 | def parser(tokens, debug=False): 27 | stack = [] 28 | output = [] 29 | ix = 0 30 | symbol = token_to_symbol(tokens[ix]) 31 | ix += 1 32 | stack.append(0) 33 | while True: 34 | state = stack[-1] 35 | action = LR[state][symbol] 36 | if debug: 37 | token = tokens[ix] if ix < len(tokens) else "-" 38 | print("tokens[ix]:",token," state:",state, " action:", action,"\t", end="") 39 | if action == []: 40 | raise Exception 41 | elif action[0] == "q": 42 | if debug: print("OK") 43 | break 44 | elif action[0] == "s": 45 | stack.append(action[1]) 46 | if debug: print("shift : push ",action, "\t",stack) 47 | symbol = token_to_symbol(tokens[ix]) 48 | ix += 1 49 | else: 50 | stack = stack[:-1*pops[action[1]]] 51 | state = LR[stack[-1]][r2n[action[1]]] 52 | if debug: print("reduce: push ",action, "\t",stack) 53 | output.append(action[1]) 54 | stack.append(state[1]) 55 | return output 56 | -------------------------------------------------------------------------------- /grammar.py: -------------------------------------------------------------------------------- 1 | 2 | BNF = [("_PROG", ["_STMT"]), 3 | ("_STMT", ["_BLOCK"]), 4 | ("_STMT", ["_ASSIGN", ";"]), 5 | ("_STMT", ["_IF"]), 6 | ("_STMT", ["_WHILE"]), 7 | ("_STMT", ["_CALLPROC", ";"]), 8 | ("_STMT", ["_TAILCALL", ";"]), 9 | ("_BLOCK", ["{", "_DECS", "_STMTS", "}"]), 10 | ("_BLOCK", ["{", "_STMTS", "}"]), 11 | ("_DECS", ["_VARDEC"]), 12 | ("_DECS", ["_FUNCDEC"]), 13 | ("_DECS", ["_DECS", "_VARDEC"]), 14 | ("_DECS", ["_DECS", "_FUNCDEC"]), 15 | ("_VARDEC", ["_INTTYP", ";"]), 16 | ("_VARDEC", ["_ARRAYTYP", ";"]), 17 | ("_INTTYP", ["int", "_ALPHABET"]), 18 | ("_ARRAYTYP", ["_INTTYP", "[", "_INTEXP", "]"]), 19 | ("_FUNCDEC", ["_INTTYP", "(", "_ARGDECS", ")", "_STMT"]), 20 | ("_FUNCDEC", ["_INTTYP", "(", ")", "_STMT"]), 21 | ("_ARGDECS", ["_ARGDEC"]), 22 | ("_ARGDECS", ["_ARGDECS", ",", "_ARGDEC"]), 23 | ("_ARGDEC", ["_INTTYP"]), 24 | ("_STMTS", ["_STMT"]), 25 | ("_STMTS", ["_STMTS", "_STMT"]), 26 | ("_ASSIGN", ["_VAR", "=", "_EXPR"]), 27 | ("_ASSIGN", ["_INDEXEDVAR", "=", "_EXPR"]), 28 | ("_VAR", ["_ALPHABET"]), 29 | ("_INDEXEDVAR",["_VAR", "[", "_EXPR", "]"]), 30 | ("_EXPR", ["_EXPR", "+", "_TERM"]), 31 | ("_EXPR", ["_EXPR", "-", "_TERM"]), 32 | ("_EXPR", ["_TERM"]), 33 | ("_TERM", ["_TERM", "*", "_FACTOR"]), 34 | ("_TERM", ["_TERM", "/", "_FACTOR"]), 35 | ("_TERM", ["_FACTOR"]), 36 | ("_FACTOR", ["(", "_EXPR", ")"]), 37 | ("_FACTOR", ["_VAREXP"]), 38 | ("_FACTOR", ["_INTEXP"]), 39 | ("_FACTOR", ["_CALLFUNC"]), 40 | ("_VAREXP", ["_VAR"]), 41 | ("_VAREXP", ["_INDEXEDVAR"]), 42 | ("_INTEXP", ["_NUMBER"]), 43 | ("_IF", ["if", "(", "_COND", ")", "_STMT", "end"]), 44 | ("_IF", ["if", "(", "_COND", ")", "_STMT", "else", "_STMT", "end"]), 45 | ("_WHILE", ["while", "(", "_COND", ")", "_STMT", "end"]), 46 | ("_COND", ["_EXPR", "<", "_EXPR"]), 47 | ("_COND", ["_EXPR", "<=", "_EXPR"]), 48 | ("_COND", ["_EXPR", ">", "_EXPR"]), 49 | ("_COND", ["_EXPR", ">=", "_EXPR"]), 50 | ("_COND", ["_EXPR", "==", "_EXPR"]), 51 | ("_COND", ["_EXPR", "!=", "_EXPR"]), 52 | ("_CALLFUNC", ["_FUNCNAME", "(", "_ARGS", ")"]), 53 | ("_CALLFUNC", ["_FUNCNAME", "(", ")"]), 54 | ("_FUNCNAME", ["_ALPHABET"]), 55 | ("_CALLPROC", ["iprint", "(", "_EXPR", ")"]), 56 | ("_CALLPROC", ["return", "_EXPR"]), 57 | ("_CALLPROC", ["_FUNCNAME", "(", "_ARGS", ")"]), 58 | ("_CALLPROC", ["_FUNCNAME", "(", ")"]), 59 | ("_ARGS", ["_ARG"]), 60 | ("_ARGS", ["_ARGS", ",", "_ARG"]), 61 | ("_ARG", ["_EXPR"]), 62 | ("_TAILCALL", ["tailcall", "_CALLPROC"])] 63 | 64 | NONTERMINAL = list(set([i[0] for i in BNF])) 65 | TERMINAL = list(set([j for i in BNF for j in i[1]]) - set(NONTERMINAL) | set(["$"])) 66 | SYMBOL = TERMINAL + NONTERMINAL 67 | 68 | -------------------------------------------------------------------------------- /old/compiler_minimal/compiler.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def tokenize(s): 4 | return s.replace("("," ( ").replace(")"," ) ").split() 5 | 6 | def parse(tokens): 7 | token = tokens.pop(0) 8 | if token == "(": 9 | L = [] 10 | while tokens[0] != ")": 11 | L.append(parse(tokens)) 12 | tokens.pop(0) 13 | return L 14 | elif token == ")": 15 | raise SyntaxError("unexpected )") 16 | else: 17 | return token 18 | 19 | def make_var(typ, level, offset): 20 | return {"typ":typ, "level":level, "offset":offset} 21 | 22 | def decs(ast_decs): 23 | assert(ast_decs[0] == "DECS") 24 | offset = 0 25 | for i in range(1, len(ast_decs)): 26 | assert(ast_decs[i][0] == "VARDEC") 27 | offset -= 8 28 | regvars[ast_decs[i][1][1]] = make_var(ast_decs[i][1][0], 0, offset) 29 | print("\tsubq $"+str(int((-offset+8)/16)*16)+", %rsp") 30 | 31 | def trans_exp(ast_exp): 32 | if ast_exp[0]=="INTEXP": 33 | print("\tpushq $"+ast_exp[1]) 34 | elif ast_exp[0]=="VAREXP": 35 | trans_var(ast_exp[1]) 36 | print("\tmovq (%rax), %rax") 37 | print("\tpushq %rax") 38 | elif ast_exp[0]=="CALLFUNC": 39 | if ast_exp[1][0]=="+": 40 | trans_exp(ast_exp[1][1]) 41 | trans_exp(ast_exp[1][2]) 42 | print("\tpopq %rax") 43 | print("\taddq %rax, (%rsp)") 44 | elif ast_exp[1][0]=="-": 45 | trans_exp(ast_exp[1][1]) 46 | trans_exp(ast_exp[1][2]) 47 | print("\tpopq %rax") 48 | print("\tsubq %rax, (%rsp)") 49 | elif ast_exp[1][0]=="*": 50 | trans_exp(ast_exp[1][1]) 51 | trans_exp(ast_exp[1][2]) 52 | print("\tpopq %rax") 53 | print("\timulq (%rsp), %rax") 54 | print("\tmovq %rax, (%rsp)") 55 | elif ast_exp[1][0]=="/": 56 | trans_exp(ast_exp[1][1]) 57 | trans_exp(ast_exp[1][2]) 58 | print("\tpopq %rbx") 59 | print("\tpopq %rax") 60 | print("\tcqto") 61 | print("\tidivq %rbx") 62 | print("\tpushq %rax") 63 | 64 | def trans_var(ast_var): 65 | assert(ast_var[0]=="VAR") 66 | offset = str(regvars[ast_var[1]]["offset"]) 67 | print("\tmovq %rbp, %rax") 68 | print("\tleaq "+offset+"(%rax), %rax") 69 | 70 | def emit(ast_stmts): 71 | assert(ast_stmts[0] == "STMTS") 72 | for i in range(1, len(ast_stmts)): 73 | if ast_stmts[i][0] == "ASSIGN": 74 | trans_exp(ast_stmts[i][2]) 75 | trans_var(ast_stmts[i][1]) 76 | print("\tpopq (%rax)") 77 | elif ast_stmts[i][0] == "CALLPROC": 78 | if ast_stmts[i][1] == "iprint": 79 | trans_exp(ast_stmts[i][2]) 80 | print("\tpopq %rsi") 81 | print("\tleaq IO(%rip), %rdi") 82 | print("\tmovq $0, %rax") 83 | print("\tcallq printf") 84 | 85 | io = "IO:\n" \ 86 | + "\t.string \"%lld\"\n" \ 87 | + "\t.text\n" 88 | header = "\t.globl main\n" \ 89 | + "main:\n" \ 90 | + "\tpushq %rbp\n" \ 91 | + "\tmovq %rsp, %rbp\n" 92 | epilogue = "\tleaveq\n" \ 93 | + "\tretq\n" 94 | 95 | def compile(ast_blocks): 96 | assert(ast_blocks[0] == "BLOCK") 97 | print(io, end="") 98 | print(header, end="") 99 | decs(ast_blocks[1]) 100 | emit(ast_blocks[2]) 101 | print(epilogue, end="") 102 | 103 | regvars = {} 104 | filename = sys.argv[1] 105 | with open(filename, "r") as f: 106 | s = f.read() 107 | ast = parse(tokenize(s)) 108 | compile(ast) 109 | 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # x86compiler 2 | A toy compiler (with SLR parser, for x86_64, written in python). 3 | 4 | ## Usage: 5 | 6 | python compiler.py SOURCE_FILE 7 | 8 | ## Examples: 9 | 10 | **Variable Declaration, Assignment, and Loading** 11 | 12 | { 13 | int a; 14 | a = 6; 15 | iprint(a); 16 | } 17 | -> 6 18 | 19 | 20 | **Arithmetic Operations** 21 | 22 | { 23 | int a; 24 | int b; 25 | a = 7; 26 | b = 3; 27 | iprint(a+1); 28 | iprint(b+1); 29 | iprint(a+b); 30 | iprint(a-b); 31 | iprint(a*b); 32 | iprint(a/b); 33 | } 34 | ->84104212 35 | 36 | **Variable Scopes** 37 | 38 | { 39 | int a; 40 | int b; 41 | a = 111; 42 | b = 123; 43 | iprint(a); 44 | iprint(b); 45 | { 46 | int a; 47 | a = 777; 48 | iprint(a); 49 | iprint(b); 50 | } 51 | iprint(a); 52 | iprint(b); 53 | } 54 | -> 111123777123111123 55 | 56 | **Arrays** 57 | 58 | { 59 | int a[3]; 60 | int b; 61 | a[0] = 1; 62 | a[1] = 2; 63 | a[2] = 3; 64 | b = 777; 65 | iprint(a[0]); 66 | iprint(a[1]); 67 | iprint(a[2]); 68 | iprint(b); 69 | { 70 | int a[3]; 71 | a[0] = 4; 72 | a[1] = 5; 73 | a[2] = 6; 74 | iprint(a[0]); 75 | iprint(a[1]); 76 | iprint(a[2]); 77 | iprint(b); 78 | } 79 | iprint(a[0]); 80 | iprint(a[1]); 81 | iprint(a[2]); 82 | iprint(b); 83 | } 84 | -> 123777456777123777 85 | 86 | **Control Structure (IF and WHILE)** 87 | 88 | { 89 | int a; 90 | int b; 91 | a = 7; 92 | b = 1; 93 | if(a!=5){ 94 | iprint(1); 95 | if(a<=5){ 96 | iprint(0); 97 | }else{ 98 | iprint(2); 99 | }end 100 | }end 101 | while(b<10){ 102 | iprint(b); 103 | b = b+1; 104 | }end 105 | } 106 | -> 12123456789 107 | 108 | **Functions** 109 | 110 | { 111 | int a[3]; 112 | int b; 113 | int f(int x, int y){ 114 | int z; 115 | z = x * y; 116 | a[1] = 777; 117 | iprint(a[1]); 118 | iprint(z); 119 | return z; 120 | iprint(z); 121 | } 122 | int g(){ 123 | iprint(999); 124 | } 125 | b = f(111, 3); 126 | g(); 127 | iprint(b); 128 | iprint(a[1]); 129 | } 130 | -> 777333999333777 131 | 132 | **Recursive Call** 133 | 134 | { 135 | int a; 136 | int f(int n){ 137 | if(n<1) 138 | return 1; 139 | else 140 | return n * f(n-1); 141 | end 142 | } 143 | a = f(5); 144 | iprint(a); 145 | } 146 | -> 120 147 | 148 | ## Notes: Development environment: 149 | 150 | - CPU: Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz 64 bits 151 | - OS: Ubuntu 14.04 LTS 152 | - gcc: 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) 153 | - python: 3.6.0 154 | 155 | ## License 156 | 157 | Copyright (c) 2023 s0sasaki 158 | 159 | Permission is hereby granted, free of charge, to any person obtaining a copy 160 | of this software and associated documentation files (the "Software"), to deal 161 | in the Software without restriction, including without limitation the rights 162 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 163 | copies of the Software, and to permit persons to whom the Software is 164 | furnished to do so, subject to the following conditions: 165 | 166 | The above copyright notice and this permission notice shall be included in all 167 | copies or substantial portions of the Software. 168 | 169 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 172 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 173 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 174 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 175 | SOFTWARE. 176 | -------------------------------------------------------------------------------- /parser_generator.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from grammar import * 3 | 4 | def make_firstset(): 5 | firstset = {i:set([]) for i in SYMBOL} 6 | for i in TERMINAL: 7 | firstset[i].add(i) 8 | for lhs, rhs in BNF: 9 | if rhs == []: 10 | firstset[lhs].add("_EPSIRON") 11 | elif rhs[0] in TERMINAL: 12 | firstset[lhs].add(rhs[0]) 13 | flag = True 14 | while flag: 15 | flag = False 16 | for lhs, rhs in BNF: 17 | for i in rhs: 18 | tmp = firstset[lhs].union(firstset[i]) 19 | if tmp != firstset[lhs]: 20 | firstset[lhs] = tmp 21 | flag = True 22 | if "_EPSIRON" not in firstset[i]: 23 | break 24 | return firstset 25 | 26 | def make_followset(firstset): 27 | followset = {i:set([]) for i in NONTERMINAL} 28 | followset["_PROG"].add("$") 29 | flag = True 30 | while flag: 31 | flag = False 32 | for lhs, rhs in BNF: 33 | for i in range(len(rhs)): 34 | if rhs[i] in TERMINAL: ### 35 | continue ### 36 | tmp_followset_i = copy.deepcopy(followset[rhs[i]]) 37 | try: 38 | inext = i+1 39 | tmp_followset_i |= firstset[rhs[inext]] 40 | while "_EPSIRON" in firstset[rhs[inext]]: 41 | inext += 1 42 | tmp_followset_i |= firstset[rhs[inext]] 43 | except IndexError: 44 | tmp_followset_i |= followset[lhs] 45 | if tmp_followset_i != followset[rhs[i]]: 46 | followset[rhs[i]] = tmp_followset_i 47 | flag = True 48 | return followset 49 | 50 | def match_closure(closure_p, closure_q): 51 | if closure_p["nBNF"] != closure_q["nBNF"]: 52 | return False 53 | for i in range(closure_p["nBNF"]): 54 | if closure_p["BNF"][i] != closure_q["BNF"][i]: 55 | return False 56 | if closure_p["dot_position"][i] != closure_q["dot_position"][i]: 57 | return False 58 | return True 59 | 60 | def make_closure(closure): 61 | i = 0 62 | while i < closure["nBNF"]: 63 | try: 64 | next_token = BNF[closure["BNF"][i]][1][closure["dot_position"][i]] 65 | except IndexError: 66 | continue 67 | finally: 68 | i += 1 69 | if next_token not in TERMINAL: 70 | for j in range(len(BNF)): 71 | if next_token != BNF[j][0]: 72 | continue 73 | new_bnf = True 74 | for l in range(closure["nBNF"]): 75 | if closure["BNF"][l]==j and closure["dot_position"][l]==0: 76 | new_bnf = False 77 | if new_bnf: 78 | closure["BNF"].append(j) 79 | closure["dot_position"].append(0) 80 | closure["checked"].append(False) 81 | closure["nBNF"] += 1 82 | return closure 83 | 84 | def search_closure(closure, closure_list): 85 | for i in range(len(closure_list)): 86 | if match_closure(closure_list[i], closure): 87 | return i 88 | return None 89 | 90 | def make_network(closure, closure_list): 91 | for i in range(closure["nBNF"]): 92 | if closure["checked"][i] or closure["dot_position"][i] >= len(BNF[closure["BNF"][i]][1]): 93 | continue 94 | closure["checked"][i] = True 95 | token = BNF[closure["BNF"][i]][1][closure["dot_position"][i]] 96 | new_closure = {} 97 | new_closure["BNF"] = [closure["BNF"][i]] 98 | new_closure["dot_position"] = [closure["dot_position"][i]+1] 99 | new_closure["checked"] = [False] 100 | new_closure["nBNF"] = 1 101 | new_closure["token"] = token 102 | new_closure["next_closure"] = [] 103 | for j in range(i+1, closure["nBNF"]): 104 | if closure["checked"][j] or closure["dot_position"][j] >= len(BNF[closure["BNF"][j]][1]): 105 | continue 106 | if BNF[closure["BNF"][j]][1][closure["dot_position"][j]] == token: 107 | closure["checked"][j] = True 108 | new_closure["BNF"].append(closure["BNF"][j]) 109 | new_closure["dot_position"].append(closure["dot_position"][j]+1) 110 | new_closure["checked"].append(False) 111 | new_closure["nBNF"] += 1 112 | new_closure = make_closure(new_closure) 113 | same_closure_ix = search_closure(new_closure, closure_list) 114 | if same_closure_ix == None: 115 | new_closure_ix = len(closure_list) 116 | closure["next_closure"].append(new_closure_ix) 117 | closure_list.append(new_closure) 118 | closure_list = make_network(new_closure, closure_list) 119 | else: 120 | closure["next_closure"].append(same_closure_ix) 121 | return closure_list 122 | 123 | def make_table(closure_list, followset): 124 | table = [{ i:[] for i in SYMBOL} for _ in closure_list] 125 | for i in range(len(closure_list)): 126 | for j in closure_list[i]["next_closure"]: 127 | table[i][closure_list[j]["token"]].append("s") 128 | table[i][closure_list[j]["token"]].append(j) 129 | for i in range(len(closure_list)): 130 | for j in range(closure_list[i]["nBNF"]): 131 | lhs = BNF[closure_list[i]["BNF"][j]][0] 132 | rhs = BNF[closure_list[i]["BNF"][j]][1] 133 | if len(rhs) != closure_list[i]["dot_position"][j]: 134 | continue 135 | for k in followset[lhs]: 136 | if lhs == "_PROG": 137 | table[i][k].append("q") 138 | else: 139 | table[i][k].append("r") 140 | table[i][k].append(closure_list[i]["BNF"][j]) 141 | for i in table: 142 | for k,v in i.items(): 143 | assert(len(v)<3) # SLR Grammar conflict! 144 | return table 145 | 146 | def parser_generator(): 147 | firstset = make_firstset() 148 | followset = make_followset(firstset) 149 | topclosure = {"nBNF": 1, 150 | "BNF": [0], 151 | "dot_position": [0], 152 | "checked": [False], 153 | "token": None, 154 | "next_closure": []} 155 | topclosure = make_closure(topclosure) 156 | closure_list = make_network(topclosure, [topclosure]) 157 | return make_table(closure_list, followset) 158 | 159 | -------------------------------------------------------------------------------- /old/compiler_backend/compiler.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import copy 3 | 4 | def tokenize(s): 5 | return s.replace("("," ( ").replace(")"," ) ").split() 6 | 7 | def parse(tokens): 8 | token = tokens.pop(0) 9 | if token == "(": 10 | L = [] 11 | while tokens[0] != ")": 12 | L.append(parse(tokens)) 13 | tokens.pop(0) 14 | return L 15 | elif token == ")": 16 | raise SyntaxError("unexpected )") 17 | else: 18 | return token 19 | 20 | def make_var(typ, nest, offset): 21 | return {"typ":typ, "nest":nest, "offset":offset} 22 | 23 | def make_func(typ, nest, arg): 24 | return {"typ":typ, "nest":nest, "arg":arg} 25 | 26 | def trans_decs(ast_decs, nest, top_offset, env, code): 27 | assert(ast_decs[0] == "DECS") 28 | delta_offset = 0 29 | for i in range(1, len(ast_decs)): 30 | if(ast_decs[i][0] == "FUNCDEC"): 31 | env[ast_decs[i][1]] = make_func(ast_decs[i][3], nest+1, ast_decs[i][2]) 32 | arg_offset = 24 33 | for j in ast_decs[i][2]: 34 | env[j[1]] = make_var(j[0], nest+1, arg_offset) 35 | arg_offset += 8 36 | tmpcode = [] 37 | tmpcode.append(ast_decs[i][1]+":") 38 | tmpcode.extend(prologue) 39 | tmpcode.append(ast_decs[i][1]+"_REC:") # CALLPROCTAIL 40 | trans_stmt(ast_decs[i][4], nest+1, 0, env, tmpcode) 41 | tmpcode.extend(epilogue) 42 | subcode.extend(tmpcode) 43 | elif(ast_decs[i][0] == "VARDEC"): 44 | if ast_decs[i][1][0] == "INTTYP": 45 | delta_offset -= 8 46 | env[ast_decs[i][1][1]] = make_var(ast_decs[i][1][0], nest, top_offset + delta_offset) 47 | elif ast_decs[i][1][0] == "ARRAYTYP": 48 | delta_offset -= 8 49 | env[ast_decs[i][1][3]] = make_var(ast_decs[i][1][2], nest, top_offset + delta_offset) 50 | delta_offset -= 8*(int(ast_decs[i][1][1])-1) 51 | return delta_offset 52 | 53 | def trans_exp(ast_exp, nest, top_offset, env, code): 54 | if ast_exp[0]=="INTEXP": 55 | code.append("\tpushq $"+ast_exp[1]) 56 | elif ast_exp[0]=="VAREXP": 57 | trans_var(ast_exp[1], nest, top_offset, env, code) 58 | code.append("\tmovq (%rax), %rax") 59 | code.append("\tpushq %rax") 60 | elif ast_exp[0]=="CALLFUNC": 61 | if ast_exp[1][0]=="+": 62 | trans_exp(ast_exp[1][1], nest, top_offset, env, code) 63 | trans_exp(ast_exp[1][2], nest, top_offset, env, code) 64 | code.append("\tpopq %rax") 65 | code.append("\taddq %rax, (%rsp)") 66 | elif ast_exp[1][0]=="-": 67 | trans_exp(ast_exp[1][1], nest, top_offset, env, code) 68 | trans_exp(ast_exp[1][2], nest, top_offset, env, code) 69 | code.append("\tpopq %rax") 70 | code.append("\tsubq %rax, (%rsp)") 71 | elif ast_exp[1][0]=="*": 72 | trans_exp(ast_exp[1][1], nest, top_offset, env, code) 73 | trans_exp(ast_exp[1][2], nest, top_offset, env, code) 74 | code.append("\tpopq %rax") 75 | code.append("\timulq (%rsp), %rax") 76 | code.append("\tmovq %rax, (%rsp)") 77 | elif ast_exp[1][0]=="/": 78 | trans_exp(ast_exp[1][1], nest, top_offset, env, code) 79 | trans_exp(ast_exp[1][2], nest, top_offset, env, code) 80 | code.append("\tpopq %rbx") 81 | code.append("\tpopq %rax") 82 | code.append("\tcqto") 83 | code.append("\tidivq %rbx") 84 | code.append("\tpushq %rax") 85 | else: 86 | ast_proc = ["CALLPROC", ast_exp[1][0], ast_exp[1][1]] 87 | trans_stmt(ast_proc, nest, top_offset, env, code) 88 | code.append("\tpushq %rax") 89 | 90 | def trans_var(ast_var, nest, top_offset, env, code): 91 | if ast_var[0]=="VAR": 92 | offset = str(env[ast_var[1]]["offset"]) 93 | code.append("\tmovq %rbp, %rax") 94 | for i in range(nest - env[ast_var[1]]["nest"]): 95 | code.append("\tmovq 16(%rax), %rax") 96 | code.append("\tleaq "+offset+"(%rax), %rax") 97 | elif ast_var[0]=="INDEXEDVAR": 98 | trans_exp(["CALLFUNC", ["*", ["INTEXP", "-8"], ast_var[2]]], nest, top_offset, env, code) 99 | trans_var(ast_var[1], nest, top_offset, env, code) 100 | code.append("\tpopq %rbx") 101 | code.append("\tleaq (%rax,%rbx), %rax") 102 | 103 | def trans_cond(ast_exp, nest, top_offset, env, code): 104 | global label 105 | if ast_exp[0]=="COND": 106 | trans_exp(ast_exp[1][1], nest, top_offset, env, code) 107 | trans_exp(ast_exp[1][2], nest, top_offset, env, code) 108 | code.append("\tpopq %rax") 109 | code.append("\tpopq %rbx") 110 | code.append("\tcmpq %rax, %rbx") 111 | label = label+1 112 | if ast_exp[1][0]=="==": code.append("\tjne L"+str(label)) 113 | elif ast_exp[1][0]=="!=": code.append("\tje L"+str(label)) 114 | elif ast_exp[1][0]==">": code.append("\tjle L"+str(label)) 115 | elif ast_exp[1][0]==">=": code.append("\tjl L"+str(label)) 116 | elif ast_exp[1][0]=="<": code.append("\tjge L"+str(label)) 117 | elif ast_exp[1][0]=="<=": code.append("\tjg L"+str(label)) 118 | 119 | 120 | def passlink(src, dst, code): 121 | if src >= dst: 122 | deltalevel = src - dst + 1 123 | code.append("\tmovq %rbp, %rax") 124 | for i in range(deltalevel): 125 | code.append("\tmovq 16(%rax), %rax") 126 | code.append("\tpushq %rax") 127 | else: 128 | code.append("\tpushq %rbp") 129 | 130 | def trans_stmts(ast_stmts, nest, top_offset, env, code): 131 | assert(ast_stmts[0] == "STMTS") 132 | for i in range(1, len(ast_stmts)): 133 | trans_stmt(ast_stmts[i], nest, top_offset, env, code) 134 | 135 | def trans_stmt(ast_stmt, nest, top_offset, env, code): 136 | global label 137 | if ast_stmt[0] == "ASSIGN": 138 | trans_exp(ast_stmt[2], nest, top_offset, env, code) 139 | trans_var(ast_stmt[1], nest, top_offset, env, code) 140 | code.append("\tpopq (%rax)") 141 | elif ast_stmt[0] == "CALLPROC": 142 | if ast_stmt[1] == "iprint": 143 | trans_exp(ast_stmt[2], nest, top_offset, env, code) 144 | code.append("\tpopq %rsi") 145 | code.append("\tleaq IO(%rip), %rdi") 146 | code.append("\tmovq $0, %rax") 147 | code.append("\tcallq printf") 148 | elif ast_stmt[1] == "return": 149 | trans_exp(ast_stmt[2], nest, top_offset, env, code) 150 | code.append("\tpopq %rax") 151 | code.extend(epilogue) 152 | else: 153 | if len(ast_stmt[2])%2 == 0: 154 | code.append("\tpushq $0") 155 | for i in reversed(ast_stmt[2]): 156 | trans_exp(i, nest, top_offset, env, code) 157 | passlink(nest, env[ast_stmt[1]]["nest"], code) 158 | code.append("\tcallq "+ast_stmt[1]) 159 | code.append("\taddq $"+str((len(ast_stmt[2])+1+1)//2*2*8)+", %rsp") 160 | elif ast_stmt[0] == "CALLPROCTAIL": 161 | arg_offset = 24 162 | for i in reversed(ast_stmt[2]): 163 | trans_exp(i, nest, top_offset, env, code) 164 | for i in ast_stmt[2]: 165 | code.append("\tmovq %rbp, %rax") 166 | code.append("\tpopq "+str(arg_offset)+"(%rax)") 167 | arg_offset += 8 168 | code.append("\tjmp "+ast_stmt[1]+"_REC") 169 | elif ast_stmt[0] == "BLOCK": 170 | local_env = copy.deepcopy(env) 171 | delta_offset = trans_decs( ast_stmt[1], nest, top_offset, local_env, code) 172 | code.append("\tsubq $"+str(int((-delta_offset+8)/16)*16)+", %rsp") 173 | trans_stmts(ast_stmt[2], nest, top_offset+delta_offset, local_env, code) 174 | code.append("\taddq $"+str(int((-delta_offset+8)/16)*16)+", %rsp") 175 | elif ast_stmt[0] == "IF": 176 | if len(ast_stmt)==3: 177 | trans_cond(ast_stmt[1], nest, top_offset, env, code) 178 | savelabel = label 179 | trans_stmt(ast_stmt[2], nest, top_offset, env, code) 180 | code.append("L"+str(savelabel)+":") 181 | else: 182 | assert(ast_stmt[3]=="ELSE") 183 | trans_cond(ast_stmt[1], nest, top_offset, env, code) 184 | oldlabel = label 185 | label = label+1 186 | newlabel = label 187 | trans_stmt(ast_stmt[2], nest, top_offset, env, code) 188 | code.append("\tjmp L"+str(newlabel)) 189 | code.append("L"+str(oldlabel)+":") 190 | trans_stmt(ast_stmt[4], nest, top_offset, env, code) 191 | code.append("L"+str(newlabel)+":") 192 | elif ast_stmt[0] == "WHILE": 193 | newlabel = label+2 194 | code.append("L"+str(newlabel)+":") 195 | trans_cond(ast_stmt[1], nest, top_offset, env, code) 196 | oldlabel = label 197 | label = label+1 198 | trans_stmt(ast_stmt[2], nest, top_offset, env, code) 199 | code.append("\tjmp L"+str(newlabel)) 200 | code.append("L"+str(oldlabel)+":") 201 | 202 | 203 | io = ["IO:", 204 | "\t.string \"%lld\"", 205 | "\t.text"] 206 | header = ["\t.globl main", 207 | "main:", 208 | "\tpushq %rbp", 209 | "\tmovq %rsp, %rbp"] 210 | prologue = ["\tpushq %rbp", 211 | "\tmovq %rsp, %rbp"] 212 | epilogue = ["\tleaveq", 213 | "\tretq"] 214 | 215 | def compile(ast): 216 | nest = 0 217 | top_offset = 0 218 | global_env = {} 219 | maincode.extend(io) 220 | maincode.extend(header) 221 | trans_stmt(ast, nest, top_offset, global_env, maincode) 222 | maincode.extend(epilogue) 223 | 224 | maincode = [] 225 | subcode = [] 226 | label = 0 227 | filename = sys.argv[1] 228 | with open(filename, "r") as f: 229 | s = f.read() 230 | ast = parse(tokenize(s)) 231 | compile(ast) 232 | 233 | for i in maincode: 234 | print(i) 235 | for i in subcode: 236 | print(i) 237 | -------------------------------------------------------------------------------- /asm_generator.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | io = ["IO:", 4 | "\t.string \"%lld\"", 5 | "\t.text"] 6 | header = ["\t.globl main", 7 | "main:", 8 | "\tpushq %rbp", 9 | "\tmovq %rsp, %rbp"] 10 | prologue = ["\tpushq %rbp", 11 | "\tmovq %rsp, %rbp"] 12 | epilogue = ["\tleaveq", 13 | "\tretq"] 14 | 15 | maincode = [] 16 | subcode = [] 17 | label = 0 18 | 19 | def make_var(typ, nest, offset): 20 | return {"typ":typ, "nest":nest, "offset":offset} 21 | 22 | def make_func(typ, nest, arg): 23 | return {"typ":typ, "nest":nest, "arg":arg} 24 | 25 | def trans_decs(ast_decs, nest, top_offset, env, code, delta_offset): 26 | assert(ast_decs[0] == "_DECS") 27 | if ast_decs[1][0] == "_DECS": 28 | delta_offset = trans_decs(ast_decs[1], nest, top_offset, env, code, delta_offset) 29 | if ast_decs[2][0] == "_VARDEC": 30 | delta_offset = trans_vardec(ast_decs[2], nest, top_offset, env, code, delta_offset) 31 | elif ast_decs[2][0] == "_FUNCDEC": 32 | trans_funcdec(ast_decs[2], nest, top_offset, env, code, delta_offset) 33 | elif ast_decs[1][0] == "_VARDEC": 34 | delta_offset = trans_vardec(ast_decs[1], nest, top_offset, env, code, delta_offset) 35 | elif ast_decs[1][0] == "_FUNCDEC": 36 | trans_funcdec(ast_decs[1], nest, top_offset, env, code, delta_offset) 37 | return delta_offset 38 | 39 | def trans_vardec(ast_vardec, nest, top_offset, env, code, delta_offset): 40 | assert(ast_vardec[0] == "_VARDEC") 41 | if ast_vardec[1][0] == "_INTTYP": 42 | return trans_inttyp(ast_vardec[1], nest, top_offset, env, code, delta_offset) 43 | elif ast_vardec[1][0] == "_ARRAYTYP": 44 | return trans_arraytyp(ast_vardec[1], nest, top_offset, env, code, delta_offset) 45 | 46 | def trans_inttyp(ast_inttyp, nest, top_offset, env, code, delta_offset): 47 | assert(ast_inttyp[0] == "_INTTYP") 48 | delta_offset -= 8 49 | env[ast_inttyp[1]] = make_var(ast_inttyp[0], nest, top_offset + delta_offset) 50 | return delta_offset 51 | 52 | def trans_arraytyp(ast_arraytyp, nest, top_offset, env, code, delta_offset): 53 | assert(ast_arraytyp[0] == "_ARRAYTYP") 54 | assert(ast_arraytyp[1][0] == "_INTTYP") 55 | assert(ast_arraytyp[2][0] == "_INTEXP") 56 | delta_offset -= 8 57 | env[ast_arraytyp[1][1]] = make_var(ast_arraytyp[1][0], nest, top_offset + delta_offset) 58 | delta_offset -= 8*(int(ast_arraytyp[2][1])-1) 59 | return delta_offset 60 | 61 | def trans_funcdec(ast_funcdec, nest, top_offset, env, code, delta_offset): 62 | assert(ast_funcdec[0] == "_FUNCDEC") 63 | assert(ast_funcdec[1][0] == "_INTTYP") 64 | if len(ast_funcdec)==3: 65 | env[ast_funcdec[1][1]] = make_func(ast_funcdec[1][0], nest+1, None) 66 | elif len(ast_funcdec)==4: 67 | env[ast_funcdec[1][1]] = make_func(ast_funcdec[1][0], nest+1, ast_funcdec[2]) 68 | trans_argdecs(ast_funcdec[2], nest+1, top_offset, env, code, delta_offset) 69 | tmpcode = [] 70 | tmpcode.append(ast_funcdec[1][1]+":") 71 | tmpcode.extend(prologue) 72 | tmpcode.append(ast_funcdec[1][1]+"_REC:") # for tailcall 73 | if len(ast_funcdec)==3: 74 | trans_stmt(ast_funcdec[2], nest+1, 0, env, tmpcode) 75 | elif len(ast_funcdec)==4: 76 | trans_stmt(ast_funcdec[3], nest+1, 0, env, tmpcode) 77 | tmpcode.extend(epilogue) 78 | subcode.extend(tmpcode) 79 | 80 | def trans_argdecs(ast_argdecs, nest, top_offset, env, code, delta_offset): 81 | assert(ast_argdecs[0] == "_ARGDECS") 82 | if ast_argdecs[1][0] == "_ARGDECS": 83 | arg_offset = trans_argdecs(ast_argdecs[1], nest, top_offset, env, code, delta_offset) 84 | trans_argdec(ast_argdecs[2], nest, top_offset, env, code, delta_offset, arg_offset) 85 | elif ast_argdecs[1][0] == "_ARGDEC": 86 | arg_offset = 24 87 | trans_argdec(ast_argdecs[1], nest, top_offset, env, code, delta_offset, arg_offset) 88 | return arg_offset + 8 89 | 90 | def trans_argdec(ast_argdec, nest, top_offset, env, code, delta_offset, arg_offset): 91 | assert(ast_argdec[0]=="_ARGDEC") 92 | assert(ast_argdec[1][0]=="_INTTYP") 93 | env[ast_argdec[1][1]] = make_var(ast_argdec[1][0], nest, arg_offset) 94 | 95 | def trans_exp(ast_exp, nest, top_offset, env, code): 96 | if ast_exp[0]=="_INTEXP": 97 | code.append("\tpushq $"+ast_exp[1]) 98 | elif ast_exp[0]=="_VAREXP": 99 | trans_var(ast_exp[1], nest, top_offset, env, code) 100 | code.append("\tmovq (%rax), %rax") 101 | code.append("\tpushq %rax") 102 | elif ast_exp[0]=="_CALLFUNC": 103 | if ast_exp[1]=="+": 104 | trans_exp(ast_exp[2], nest, top_offset, env, code) 105 | trans_exp(ast_exp[3], nest, top_offset, env, code) 106 | code.append("\tpopq %rax") 107 | code.append("\taddq %rax, (%rsp)") 108 | elif ast_exp[1]=="-": 109 | trans_exp(ast_exp[2], nest, top_offset, env, code) 110 | trans_exp(ast_exp[3], nest, top_offset, env, code) 111 | code.append("\tpopq %rax") 112 | code.append("\tsubq %rax, (%rsp)") 113 | elif ast_exp[1]=="*": 114 | trans_exp(ast_exp[2], nest, top_offset, env, code) 115 | trans_exp(ast_exp[3], nest, top_offset, env, code) 116 | code.append("\tpopq %rax") 117 | code.append("\timulq (%rsp), %rax") 118 | code.append("\tmovq %rax, (%rsp)") 119 | elif ast_exp[1]=="/": 120 | trans_exp(ast_exp[2], nest, top_offset, env, code) 121 | trans_exp(ast_exp[3], nest, top_offset, env, code) 122 | code.append("\tpopq %rbx") 123 | code.append("\tpopq %rax") 124 | code.append("\tcqto") 125 | code.append("\tidivq %rbx") 126 | code.append("\tpushq %rax") 127 | else: 128 | ast_proc = ["_CALLPROC", ast_exp[1], ast_exp[2]] 129 | trans_callproc(ast_proc, nest, top_offset, env, code) 130 | code.append("\tpushq %rax") 131 | 132 | def trans_var(ast_var, nest, top_offset, env, code): 133 | if ast_var[0]=="_VAR": 134 | offset = str(env[ast_var[1]]["offset"]) 135 | code.append("\tmovq %rbp, %rax") 136 | for i in range(nest - env[ast_var[1]]["nest"]): 137 | code.append("\tmovq 16(%rax), %rax") 138 | code.append("\tleaq "+offset+"(%rax), %rax") 139 | elif ast_var[0]=="_INDEXEDVAR": 140 | trans_exp(["_CALLFUNC", "*", ["_INTEXP", "-8"], ast_var[2]], nest, top_offset, env, code) 141 | trans_var(ast_var[1], nest, top_offset, env, code) 142 | code.append("\tpopq %rbx") 143 | code.append("\tleaq (%rax,%rbx), %rax") 144 | 145 | def trans_cond(ast_exp, nest, top_offset, env, code): 146 | global label 147 | if ast_exp[0]=="_COND": 148 | trans_exp(ast_exp[2], nest, top_offset, env, code) 149 | trans_exp(ast_exp[3], nest, top_offset, env, code) 150 | code.append("\tpopq %rax") 151 | code.append("\tpopq %rbx") 152 | code.append("\tcmpq %rax, %rbx") 153 | label = label+1 154 | if ast_exp[1]=="==": code.append("\tjne L"+str(label)) 155 | elif ast_exp[1]=="!=": code.append("\tje L"+str(label)) 156 | elif ast_exp[1]==">": code.append("\tjle L"+str(label)) 157 | elif ast_exp[1]==">=": code.append("\tjl L"+str(label)) 158 | elif ast_exp[1]=="<": code.append("\tjge L"+str(label)) 159 | elif ast_exp[1]=="<=": code.append("\tjg L"+str(label)) 160 | 161 | def passlink(src, dst, code): 162 | if src >= dst: 163 | deltalevel = src - dst + 1 164 | code.append("\tmovq %rbp, %rax") 165 | for i in range(deltalevel): 166 | code.append("\tmovq 16(%rax), %rax") 167 | code.append("\tpushq %rax") 168 | else: 169 | code.append("\tpushq %rbp") 170 | 171 | def trans_stmts(ast_stmts, nest, top_offset, env, code): 172 | assert(ast_stmts[0] == "_STMTS") 173 | if ast_stmts[1][0] == "_STMTS": 174 | trans_stmts(ast_stmts[1], nest, top_offset, env, code) 175 | trans_stmt( ast_stmts[2], nest, top_offset, env, code) 176 | elif ast_stmts[1][0] == "_STMT": 177 | trans_stmt( ast_stmts[1], nest, top_offset, env, code) 178 | 179 | def trans_stmt(ast_stmt, nest, top_offset, env, code): 180 | assert(ast_stmt[0] == "_STMT") 181 | if ast_stmt[1][0] == "_ASSIGN": 182 | trans_assign(ast_stmt[1], nest, top_offset, env, code) 183 | elif ast_stmt[1][0] == "_BLOCK": 184 | trans_block(ast_stmt[1], nest, top_offset, env, code) 185 | elif ast_stmt[1][0] == "_IF": 186 | trans_if(ast_stmt[1], nest, top_offset, env, code) 187 | elif ast_stmt[1][0] == "_WHILE": 188 | trans_while(ast_stmt[1], nest, top_offset, env, code) 189 | elif ast_stmt[1][0] == "_CALLPROC": 190 | trans_callproc(ast_stmt[1], nest, top_offset, env, code) 191 | elif ast_stmt[1][0] == "_TAILCALL": 192 | trans_tailcall(ast_stmt[1], nest, top_offset, env, code) 193 | 194 | def trans_assign(ast_assign, nest, top_offset, env, code): 195 | assert(ast_assign[0] == "_ASSIGN") 196 | trans_exp(ast_assign[2], nest, top_offset, env, code) 197 | trans_var(ast_assign[1], nest, top_offset, env, code) 198 | code.append("\tpopq (%rax)") 199 | 200 | def trans_block(ast_block, nest, top_offset, env, code): 201 | assert(ast_block[0] == "_BLOCK") 202 | local_env = copy.deepcopy(env) 203 | if len(ast_block) == 3: 204 | delta_offset = trans_decs(ast_block[1], nest, top_offset, local_env, code, 0) 205 | code.append("\tsubq $"+str(int((-delta_offset+8)/16)*16)+", %rsp") 206 | trans_stmts(ast_block[2], nest, top_offset+delta_offset, local_env, code) 207 | code.append("\taddq $"+str(int((-delta_offset+8)/16)*16)+", %rsp") 208 | else: 209 | trans_stmts(ast_block[1], nest, top_offset, local_env, code) 210 | 211 | def trans_if(ast_if, nest, top_offset, env, code): 212 | assert(ast_if[0] == "_IF") 213 | global label 214 | if len(ast_if) == 3: 215 | trans_cond(ast_if[1], nest, top_offset, env, code) 216 | savelabel = label 217 | trans_stmt(ast_if[2], nest, top_offset, env, code) 218 | code.append("L"+str(savelabel)+":") 219 | else: 220 | trans_cond(ast_if[1], nest, top_offset, env, code) 221 | oldlabel = label 222 | label = label+1 223 | newlabel = label 224 | trans_stmt(ast_if[2], nest, top_offset, env, code) 225 | code.append("\tjmp L"+str(newlabel)) 226 | code.append("L"+str(oldlabel)+":") 227 | trans_stmt(ast_if[3], nest, top_offset, env, code) 228 | code.append("L"+str(newlabel)+":") 229 | 230 | def trans_while(ast_while, nest, top_offset, env, code): 231 | assert(ast_while[0] == "_WHILE") 232 | global label 233 | newlabel = label+2 234 | code.append("L"+str(newlabel)+":") 235 | trans_cond(ast_while[1], nest, top_offset, env, code) 236 | oldlabel = label 237 | label = label+1 238 | trans_stmt(ast_while[2], nest, top_offset, env, code) 239 | code.append("\tjmp L"+str(newlabel)) 240 | code.append("L"+str(oldlabel)+":") 241 | 242 | def trans_callproc(ast_callproc, nest, top_offset, env, code): 243 | assert(ast_callproc[0] == "_CALLPROC") 244 | if ast_callproc[1] == "iprint": 245 | trans_exp(ast_callproc[2], nest, top_offset, env, code) 246 | code.append("\tpopq %rsi") 247 | code.append("\tleaq IO(%rip), %rdi") 248 | code.append("\tmovq $0, %rax") 249 | code.append("\tcallq printf") 250 | elif ast_callproc[1] == "return": 251 | trans_exp(ast_callproc[2], nest, top_offset, env, code) 252 | code.append("\tpopq %rax") 253 | code.extend(epilogue) 254 | else: 255 | args = ast_callproc[2] if len(ast_callproc)==3 else [] 256 | arglength = count_args(args) 257 | if arglength%2 == 0: 258 | code.append("\tpushq $0") 259 | trans_args(args, nest, top_offset, env, code) 260 | passlink(nest, env[ast_callproc[1][1]]["nest"], code) 261 | code.append("\tcallq "+ast_callproc[1][1]) 262 | code.append("\taddq $"+str((arglength+1+1)//2*2*8)+", %rsp") 263 | 264 | def count_args(args): 265 | if args == [] or args[0]=="_ARG": 266 | return 0 267 | elif args[0]=="_ARGS": 268 | return 1+count_args(args[1]) 269 | 270 | def trans_args(args, nest, top_offset, env, code): 271 | if args == []: 272 | return 273 | elif args[1][0] == "_ARGS": 274 | trans_arg( args[2], nest, top_offset, env, code) 275 | trans_args(args[1], nest, top_offset, env, code) 276 | elif args[1][0] == "_ARG": 277 | trans_arg( args[1], nest, top_offset, env, code) 278 | 279 | def trans_arg(arg, nest, top_offset, env, code): 280 | assert(arg[0] == "_ARG") 281 | trans_exp(arg[1], nest, top_offset, env, code) 282 | 283 | def trans_tailcall(ast_tailcall, nest, top_offset, env, code): 284 | assert(ast_tailcall[0] == "_TAILCALL") 285 | assert(ast_tailcall[1][0] == "_CALLPROC") 286 | args = ast_tailcall[1][2] if len(ast_tailcall[1])==3 else [] 287 | arglength = count_args(args) 288 | trans_args(args, nest, top_offset, env, code) 289 | for i in range(arglength): 290 | code.append("\tmovq %rbp, %rax") 291 | code.append("\tpopq "+str(24 + i*8)+"(%rax)") 292 | code.append("\tjmp "+ast_tailcall[1][1][1]+"_REC") 293 | 294 | def asm_generator(ast): 295 | nest = 0 296 | top_offset = 0 297 | global_env = {} 298 | maincode.extend(io) 299 | maincode.extend(header) 300 | trans_stmt(ast, nest, top_offset, global_env, maincode) 301 | maincode.extend(epilogue) 302 | return maincode + subcode 303 | 304 | 305 | --------------------------------------------------------------------------------