From 1033f1cf57cd0b3398396b579dd8c7dd6359234b Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 17 Jun 2024 13:49:49 +0530 Subject: [PATCH 01/12] Implement `while` --- src/backend/c-lisp.py | 31 +++++++++++++++++++ .../tests/c-lisp/bisection-rootfind.sexp | 6 ++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index 2a0e3a9..fe859d2 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -87,6 +87,8 @@ def gen_stmt(self, stmt): return self.gen_if_stmt(stmt) elif self.is_for_stmt(stmt): return self.gen_for_stmt(stmt) + elif self.is_while_stmt(stmt): + return self.gen_while_stmt(stmt) else: return self.gen_expr(stmt) else: @@ -95,6 +97,35 @@ def gen_stmt(self, stmt): print(f"Error in statement: {stmt}") raise e + def is_while_stmt(self, stmt): + return stmt[0] == "while" + + def gen_while_stmt(self, stmt): + if len(stmt) < 3: + raise CodegenError(f"Bad while statement: {stmt}") + + cond_sym, loop_lbl, cont_lbl, break_lbl = [ + random_label(CLISP_PREFIX, [extra]) + for extra in ( + "cond", + "loop", + "cont", + "break", + ) + ] + cond_expr_instr = self.gen_expr(stmt[1], res_sym=cond_sym) + loop_stmt_instr = self.gen_stmt(stmt[2:]) + + return [ + ["label", loop_lbl], + *cond_expr_instr, + ["br", cond_sym, cont_lbl, break_lbl], + ["label", cont_lbl], + *loop_stmt_instr, + ["jmp", loop_lbl], + ["label", break_lbl], + ] + def is_for_stmt(self, stmt): return stmt[0] == "for" diff --git a/src/backend/tests/c-lisp/bisection-rootfind.sexp b/src/backend/tests/c-lisp/bisection-rootfind.sexp index 1aa3445..f725b3a 100644 --- a/src/backend/tests/c-lisp/bisection-rootfind.sexp +++ b/src/backend/tests/c-lisp/bisection-rootfind.sexp @@ -19,10 +19,8 @@ (declare (mid-pt float)) (declare (loop bool)) - (for ((set loop #t); TODO: Use `while` and `break` once implemented - loop - 0) - + (set loop #t) + (while loop (set mid-pt (fdiv (fadd pos-pt neg-pt) 2.0)) (set mid-val From e2a159c27cd82b2a0d808eb85601ba616a2c5a08 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 17 Jun 2024 17:19:14 +0530 Subject: [PATCH 02/12] Implement scopes --- src/backend/c-lisp.py | 53 +++++++++++++++++++++-------- src/backend/tests/c-lisp/scope.out | 2 ++ src/backend/tests/c-lisp/scope.sexp | 22 ++++++++++++ 3 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 src/backend/tests/c-lisp/scope.out create mode 100644 src/backend/tests/c-lisp/scope.sexp diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index fe859d2..c52c764 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -14,6 +14,7 @@ class BrilispCodeGenerator: def __init__(self): # Type tracking self.symbol_types = {} # Variable name -> type + self.scopes = [] # Stack of scope tags self.function_types = {} # Function name > (ret-type, (arg-types...)) self.binary_op_types = { @@ -51,6 +52,13 @@ def c_lisp(self, prog): return ["brilisp"] + [self.gen_function(fn) for fn in prog[1:]] + def get_scoped_name(self, name): + for scope in self.scopes[::-1]: + scoped_name = f"{name}.{scope}" + if scoped_name in self.symbol_types: + return scoped_name + return f"{name}.{self.scopes[-1]}" + def gen_function(self, func): if not func[0] == "define": raise CodegenError(f"Not a function: {func}") @@ -59,18 +67,21 @@ def gen_function(self, func): if not len(elem) == 2: raise CodegenError(f"Bad function prototype: {func[1]}") - self.symbol_types = {} # Clear the symbol table + # Clear the symbol table and scope stack + self.symbol_types = {} + self.scopes = [random_label(CLISP_PREFIX, ["scope"])] + name, ret_type = func[1][0] parm_types = [] + header = func[1][0:1] for parm in func[1][1:]: - parm_types.append(parm[1]) - self.symbol_types[parm[0]] = parm[1] + typ = parm[1] + scoped_name = self.get_scoped_name(parm[0]) + parm_types.append(typ) + self.symbol_types[scoped_name] = typ + header.append([scoped_name, typ]) self.function_types[name] = [ret_type, parm_types] - return [ - "define", - func[1], - *self.gen_stmt(func[2:]), - ] + return ["define", header, *self.gen_compound_stmt(func[2:], new_scope=False)] def gen_stmt(self, stmt): try: @@ -201,9 +212,10 @@ def gen_decl_stmt(self, stmt): raise CodegenError(f"bad declare statement: {stmt}") name, typ = stmt[1] - if name in self.symbol_types: + scoped_name = f"{name}.{self.scopes[-1]}" + if scoped_name in self.symbol_types: raise CodegenError(f"Re-declaration of variable {name}") - self.symbol_types[name] = typ + self.symbol_types[scoped_name] = typ return [] def is_ret_stmt(self, stmt): @@ -225,10 +237,15 @@ def gen_ret_stmt(self, stmt): def is_compound_stmt(self, stmt): return isinstance(stmt, list) and isinstance(stmt[0], list) - def gen_compound_stmt(self, stmt): + def gen_compound_stmt(self, stmt, new_scope=True): + if new_scope: + scope = random_label(CLISP_PREFIX, ["scope"]) + self.scopes.append(scope) instr_list = [] for s in stmt: instr_list += self.gen_stmt(s) + if new_scope: + self.scopes.pop() return instr_list def is_set_expr(self, expr): @@ -236,11 +253,14 @@ def is_set_expr(self, expr): def gen_set_expr(self, expr, res_sym): name = expr[1] - if not name in self.symbol_types: + scoped_name = self.get_scoped_name(name) + if not scoped_name in self.symbol_types: raise CodegenError(f"Cannot set undeclared variable: {name}") instr_list = self.gen_expr(expr[2], res_sym=res_sym) - instr_list.append(["set", [name, self.symbol_types[name]], ["id", res_sym]]) + instr_list.append( + ["set", [scoped_name, self.symbol_types[scoped_name]], ["id", res_sym]] + ) return instr_list def get_literal_type(self, expr): @@ -279,8 +299,11 @@ def is_var_expr(self, expr): return isinstance(expr, str) def gen_var_expr(self, expr, res_sym): - if expr in self.symbol_types: - return [["set", [res_sym, self.symbol_types[expr]], ["id", expr]]] + scoped_name = self.get_scoped_name(expr) + if scoped_name in self.symbol_types: + return [ + ["set", [res_sym, self.symbol_types[scoped_name]], ["id", scoped_name]] + ] else: raise CodegenError(f"Reference to undeclared variable: {expr}") diff --git a/src/backend/tests/c-lisp/scope.out b/src/backend/tests/c-lisp/scope.out new file mode 100644 index 0000000..4adacaf --- /dev/null +++ b/src/backend/tests/c-lisp/scope.out @@ -0,0 +1,2 @@ +45 +0 diff --git a/src/backend/tests/c-lisp/scope.sexp b/src/backend/tests/c-lisp/scope.sexp new file mode 100644 index 0000000..c189fb3 --- /dev/null +++ b/src/backend/tests/c-lisp/scope.sexp @@ -0,0 +1,22 @@ +(c-lisp + (define ((print int) (n int))) + + (define ((main void)) + (declare (sum1 int)) + (set sum1 0) + (declare (sum2 int)) + (set sum2 0) + + (declare (same-name int)) + + (for ((set same-name 0) + (lt same-name 10) + (set same-name (add same-name 1))) + ((declare (same-name int)) + (set same-name 0) + (set sum2 (add sum2 same-name))) + (set sum1 (add sum1 same-name))) + + (call print sum1) + (call print sum2) + (ret))) From 1472966aaa5712967b5266ebc040c4388505e110 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Tue, 18 Jun 2024 22:18:52 +0530 Subject: [PATCH 03/12] Support for 1-D arrays: load, store, alloc and ptradd --- src/backend/c-lisp.py | 78 ++++++++++++++++++++++++- src/backend/tests/c-lisp/array-sum.out | 1 + src/backend/tests/c-lisp/array-sum.sexp | 29 +++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/backend/tests/c-lisp/array-sum.out create mode 100644 src/backend/tests/c-lisp/array-sum.sexp diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index c52c764..17cb593 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -16,6 +16,7 @@ def __init__(self): self.symbol_types = {} # Variable name -> type self.scopes = [] # Stack of scope tags self.function_types = {} # Function name > (ret-type, (arg-types...)) + self.pointer_types = {} # For internal use, e.g. temporary pointer variables self.binary_op_types = { # : @@ -301,9 +302,13 @@ def is_var_expr(self, expr): def gen_var_expr(self, expr, res_sym): scoped_name = self.get_scoped_name(expr) if scoped_name in self.symbol_types: - return [ - ["set", [res_sym, self.symbol_types[scoped_name]], ["id", scoped_name]] + typ = self.symbol_types[scoped_name] + instr_list = [ + ["set", [res_sym, typ], ["id", scoped_name]] ] + if typ[0] == "ptr": + self.pointer_types[res_sym] = typ + return instr_list else: raise CodegenError(f"Reference to undeclared variable: {expr}") @@ -326,6 +331,67 @@ def gen_binary_expr(self, expr, res_sym): ["set", [res_sym, typ], [opcode, in1_sym, in2_sym]], ] + def is_ptradd_expr(self, expr): + return expr[0] == "ptradd" + + def gen_ptradd_expr(self, expr, res_sym): + if len(expr) != 3: + raise CodegenError(f"Bad ptradd expression: {expr}") + + offset_sym = random_label("tmp_clisp") + ptr_name = self.get_scoped_name(expr[1]) + ptr_type = self.symbol_types[ptr_name] + self.pointer_types[res_sym] = ptr_type + return [ + *self.gen_expr(expr[2], res_sym=offset_sym), + ["set", [res_sym, ptr_type], ["ptradd", ptr_name, offset_sym]], + ] + + def is_load_expr(self, expr): + return expr[0] == "load" + + def gen_load_expr(self, expr, res_sym): + if len(expr) != 2: + raise CodegenError(f"Bad load expression: {expr}") + + ptr_sym = random_label("tmp_clisp") + return [ + *self.gen_expr(expr[1], res_sym=ptr_sym), + ["set", [res_sym, self.pointer_types[ptr_sym][1]], ["load", ptr_sym]], + ] + + def is_store_expr(self, expr): + return expr[0] == "store" + + def gen_store_expr(self, expr, res_sym): + if len(expr) != 3: + raise CodegenError(f"Bad store expression: {expr}") + + val_sym, ptr_sym = [ + random_label(CLISP_PREFIX, [extra]) for extra in ("val", "ptr") + ] + return [ + *self.gen_expr(expr[1], res_sym=ptr_sym), + *self.gen_expr(expr[2], res_sym=val_sym), + ["store", ptr_sym, val_sym], + ["set", [res_sym, self.pointer_types[ptr_sym][1]], ["id", val_sym]], + ] + + def is_alloc_expr(self, expr): + return expr[0] == "alloc" + + def gen_alloc_expr(self, expr, res_sym): + if len(expr) != 3: + raise CodegenError(f"Bad alloc expression: {expr}") + + ptr_type = ["ptr", expr[1]] + self.pointer_types[res_sym] = ptr_type + size_sym = random_label(CLISP_PREFIX) + return [ + *self.gen_expr(expr[2], res_sym=size_sym), + ["set", [res_sym, ptr_type], ["alloc", size_sym]], + ] + def gen_expr(self, expr, res_sym=None): res_sym = res_sym or random_label(CLISP_PREFIX) if self.is_literal_expr(expr): @@ -338,6 +404,14 @@ def gen_expr(self, expr, res_sym=None): return self.gen_var_expr(expr, res_sym) elif self.is_binary_expr(expr): return self.gen_binary_expr(expr, res_sym) + elif self.is_ptradd_expr(expr): + return self.gen_ptradd_expr(expr, res_sym) + elif self.is_load_expr(expr): + return self.gen_load_expr(expr, res_sym) + elif self.is_store_expr(expr): + return self.gen_store_expr(expr, res_sym) + elif self.is_alloc_expr(expr): + return self.gen_alloc_expr(expr, res_sym) else: raise CodegenError(f"Bad expression: {expr}") diff --git a/src/backend/tests/c-lisp/array-sum.out b/src/backend/tests/c-lisp/array-sum.out new file mode 100644 index 0000000..ea90ee3 --- /dev/null +++ b/src/backend/tests/c-lisp/array-sum.out @@ -0,0 +1 @@ +45 diff --git a/src/backend/tests/c-lisp/array-sum.sexp b/src/backend/tests/c-lisp/array-sum.sexp new file mode 100644 index 0000000..7664d4a --- /dev/null +++ b/src/backend/tests/c-lisp/array-sum.sexp @@ -0,0 +1,29 @@ +(c-lisp + (define ((print int) (n int))) + + (define ((arr_sum int) (a (ptr int)) (n int)) + (declare (i int)) + (declare (sum int)) + (set sum 0) + + (for ((set i 0) + (lt i n) + (set i (add i 1))) + (set sum (add sum (load (ptradd a i))))) + (ret sum)) + + (define ((main void)) + (declare (arr (ptr int))) + (declare (i int)) + (declare (arr_i (ptr int))) + + (set arr (alloc int 10)) + + (for ((set i 0) + (lt i 10) + (set i (add i 1))) + (set arr_i (ptradd arr i)) + (store arr_i i)) + + (call print (call arr_sum arr 10)) + (ret))) From e1913dee6bca0f77610c1a5bd9cf452df99c6b96 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Wed, 19 Jun 2024 23:25:33 +0530 Subject: [PATCH 04/12] New tests: `matrix-sum`, `transpose`, and one new case for `array-sum` --- src/backend/tests/c-lisp/array-sum.out | 1 + src/backend/tests/c-lisp/array-sum.sexp | 15 ++++-- src/backend/tests/c-lisp/matrix-sum.out | 16 ++++++ src/backend/tests/c-lisp/matrix-sum.sexp | 64 ++++++++++++++++++++++++ src/backend/tests/c-lisp/transpose.out | 25 +++++++++ src/backend/tests/c-lisp/transpose.sexp | 58 +++++++++++++++++++++ 6 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 src/backend/tests/c-lisp/matrix-sum.out create mode 100644 src/backend/tests/c-lisp/matrix-sum.sexp create mode 100644 src/backend/tests/c-lisp/transpose.out create mode 100644 src/backend/tests/c-lisp/transpose.sexp diff --git a/src/backend/tests/c-lisp/array-sum.out b/src/backend/tests/c-lisp/array-sum.out index ea90ee3..daca503 100644 --- a/src/backend/tests/c-lisp/array-sum.out +++ b/src/backend/tests/c-lisp/array-sum.out @@ -1 +1,2 @@ 45 +285 diff --git a/src/backend/tests/c-lisp/array-sum.sexp b/src/backend/tests/c-lisp/array-sum.sexp index 7664d4a..236f73d 100644 --- a/src/backend/tests/c-lisp/array-sum.sexp +++ b/src/backend/tests/c-lisp/array-sum.sexp @@ -13,17 +13,22 @@ (ret sum)) (define ((main void)) - (declare (arr (ptr int))) + (declare (arr1 (ptr int))) + (declare (arr2 (ptr int))) (declare (i int)) (declare (arr_i (ptr int))) - (set arr (alloc int 10)) + (set arr1 (alloc int 10)) + (set arr2 (alloc int 10)) (for ((set i 0) (lt i 10) (set i (add i 1))) - (set arr_i (ptradd arr i)) - (store arr_i i)) + (set arr_i (ptradd arr1 i)) + (store arr_i i) + (set arr_i (ptradd arr2 i)) + (store arr_i (mul i i))) - (call print (call arr_sum arr 10)) + (call print (call arr_sum arr1 10)) + (call print (call arr_sum arr2 10)) (ret))) diff --git a/src/backend/tests/c-lisp/matrix-sum.out b/src/backend/tests/c-lisp/matrix-sum.out new file mode 100644 index 0000000..5c0a7d7 --- /dev/null +++ b/src/backend/tests/c-lisp/matrix-sum.out @@ -0,0 +1,16 @@ +22 +24 +26 +28 +42 +44 +46 +48 +62 +64 +66 +68 +82 +84 +86 +88 diff --git a/src/backend/tests/c-lisp/matrix-sum.sexp b/src/backend/tests/c-lisp/matrix-sum.sexp new file mode 100644 index 0000000..4f75b70 --- /dev/null +++ b/src/backend/tests/c-lisp/matrix-sum.sexp @@ -0,0 +1,64 @@ +(c-lisp + (define ((malloc (ptr int)) (bytes int))) + (define ((free void) (arr (ptr int)))) + (define ((print int) (n int))) + + (define ((index int) (i int) (j int) (len int)) + (ret (add (mul i len) j))) + + (define ((mat-cons void) (arr (ptr int)) (len int)) + (declare (i int)) + (declare (j int)) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (for ((set j 0) + (lt j len) + (set j (add j 1))) + (store + (ptradd arr (call index i j len)) + (add 11 (add (mul i 10) j))))) + (ret)) + + (define ((mat-add (ptr int)) (a (ptr int)) (b (ptr int)) (len int)) + (declare (i int)) + (declare (j int)) + (declare (idx int)) + + (declare (res (ptr int))) + (set res (call malloc (mul (mul len len) 4))) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (for ((set j 0) + (lt j len) + (set j (add j 1))) + (set idx (call index i j len)) + (store + (ptradd res idx) + (add + (load (ptradd a idx)) + (load (ptradd b idx)))))) + (ret res)) + + (define ((main void)) + (declare (in1 (ptr int))) + (declare (in2 (ptr int))) + (declare (out (ptr int))) + + (set in1 (alloc int 16)) + (call mat-cons in1 4) + (set in2 (alloc int 16)) + (call mat-cons in2 4) + + (set out (call mat-add in1 in2 4)) + + (declare (i int)) + (for ((set i 0) + (lt i 16) + (set i (add i 1))) + (call print (load (ptradd out i)))) + (call free out) + (ret))) diff --git a/src/backend/tests/c-lisp/transpose.out b/src/backend/tests/c-lisp/transpose.out new file mode 100644 index 0000000..6a37be3 --- /dev/null +++ b/src/backend/tests/c-lisp/transpose.out @@ -0,0 +1,25 @@ +11 +21 +31 +41 +51 +12 +22 +32 +42 +52 +13 +23 +33 +43 +53 +14 +24 +34 +44 +54 +15 +25 +35 +45 +55 diff --git a/src/backend/tests/c-lisp/transpose.sexp b/src/backend/tests/c-lisp/transpose.sexp new file mode 100644 index 0000000..47af23f --- /dev/null +++ b/src/backend/tests/c-lisp/transpose.sexp @@ -0,0 +1,58 @@ +(c-lisp + (define ((print int) (n int))) + + (define ((swap void) (a (ptr int)) (b (ptr int))) + (declare (tmp int)) + (set tmp (load b)) + (store b (load a)) + (store a tmp) + (ret)) + + (define ((index int) (i int) (j int) (len int)) + (ret (add (mul i len) j))) + + (define ((transpose void) (mat (ptr int)) (len int)) + (declare (i int)) + (declare (j int)) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (for ((set j (add i 1)) + (lt j len) + (set j (add j 1))) + (call swap (ptradd mat (call index i j len)) (ptradd mat (call index j i len))))) + (ret)) + + (define ((mat-cons void) (arr (ptr int)) (len int)) + (declare (i int)) + (declare (j int)) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (for ((set j 0) + (lt j len) + (set j (add j 1))) + (store + (ptradd arr (call index i j len)) + (add 11 (add (mul i 10) j))))) + (ret)) + + (define ((arr-print void) (arr (ptr int)) (len int)) + (declare (i int)) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (call print (load (ptradd arr i)))) + (ret)) + + (define ((main void)) + (declare (input (ptr int))) + + (set input (alloc int 25)) + (call mat-cons input 5) + (call transpose input 5) + (call arr-print input 25) + (ret))) From f0483a6ce1bca11f1c6a98edbad4d71930087e5b Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Thu, 20 Jun 2024 08:57:00 +0530 Subject: [PATCH 05/12] Add test: `gaussian-elimination` --- src/backend/c-lisp.py | 4 + src/backend/tests/brilisp/run.sh | 2 +- .../tests/c-lisp/gaussian-elimination.out | 9 ++ .../tests/c-lisp/gaussian-elimination.sexp | 83 +++++++++++++++++++ src/backend/tests/c-lisp/turnt.toml | 2 +- 5 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/backend/tests/c-lisp/gaussian-elimination.out create mode 100644 src/backend/tests/c-lisp/gaussian-elimination.sexp diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index 17cb593..c948fd5 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -44,6 +44,10 @@ def __init__(self): "fgt": "bool", "fle": "bool", "fge": "bool", + # Boolean logic + "and": "bool", + "or": "bool", + "not": "bool", } def c_lisp(self, prog): diff --git a/src/backend/tests/brilisp/run.sh b/src/backend/tests/brilisp/run.sh index a4b4466..3dde5cd 100644 --- a/src/backend/tests/brilisp/run.sh +++ b/src/backend/tests/brilisp/run.sh @@ -6,6 +6,6 @@ tmp_out=$(mktemp --suffix '.out') cp /dev/stdin $tmp_in clang $tmp_in runtime.c -o $tmp_out -Wno-override-module -O2 -$tmp_out +$tmp_out $@ rm $tmp_in $tmp_out diff --git a/src/backend/tests/c-lisp/gaussian-elimination.out b/src/backend/tests/c-lisp/gaussian-elimination.out new file mode 100644 index 0000000..89a610f --- /dev/null +++ b/src/backend/tests/c-lisp/gaussian-elimination.out @@ -0,0 +1,9 @@ +1.000000 +-1.000000 +1.000000 +0.000000 +1.000000 +-12.000000 +0.000000 +0.000000 +57.000000 diff --git a/src/backend/tests/c-lisp/gaussian-elimination.sexp b/src/backend/tests/c-lisp/gaussian-elimination.sexp new file mode 100644 index 0000000..ba5fb61 --- /dev/null +++ b/src/backend/tests/c-lisp/gaussian-elimination.sexp @@ -0,0 +1,83 @@ +;; ARGS: 3 3 1 -1 1 3 -2 -9 2 3 -1 +(c-lisp + (define ((print int) (n int))) + (define ((fprint float) (n float))) + (define ((index int) (i int) (j int) (ncols int))) + (define ((strtof float) (s (ptr int)) (end int))) + (define ((atoi int) (s (ptr int)))) + + (define ((row-op void) (mod (ptr float)) (ref (ptr float)) (len int)) ; mod -> mod - factor*ref + (declare (i int)) + (declare (mod_p (ptr float))) + (declare (l float)) + (declare (pv int)) + + (for ((set pv 0) + (and + (feq (load (ptradd mod pv)) 0.0) + (lt pv len)) + (set pv (add pv 1))) + ()) + + (if (lt pv len) + (set l + (fdiv + (load (ptradd mod pv)) + (load (ptradd ref pv)))) + (ret)) + + (for ((set i pv) + (lt i len) + (set i (add i 1))) + (store + (set mod_p (ptradd mod i)) + (fsub + (load mod_p) + (fmul l (load (ptradd ref i)))))) + ;(call fprint (load mod_p)) + (ret)) + + (define ((gaussian-eli void) (mat (ptr float)) (nrows int) (ncols int)) + (declare (ref-row int)) + (declare (mod-row int)) + (declare (col int)) + + (for ((set ref-row 0) + (lt ref-row (sub nrows 1)) + (set ref-row (add ref-row 1))) + (for ((set mod-row (add ref-row 1)) + (lt mod-row nrows) + (set mod-row (add mod-row 1))) + (call row-op + (ptradd mat (mul ncols mod-row)) + (ptradd mat (mul ncols ref-row)) + ncols))) + + (ret)) + + (define ((main void) (argc int) (argv (ptr (ptr int)))) + (declare (input (ptr float))) + (declare (nr int)) + (declare (nc int)) + (declare (sz int)) + (declare (i int)) + + (set nr (call atoi (load (ptradd argv 1)))) + (set nc (call atoi (load (ptradd argv 2)))) + (set sz (mul nr nc)) + (set input (alloc float sz)) + + (for ((set i 0) + (lt i sz) + (set i (add i 1))) + (store + (ptradd input i) + (call strtof (load (ptradd argv (add i 3))) 0))) + + (call gaussian-eli input nr nc) + (for ((set i 0) + (lt i sz) + (set i (add i 1))) + (call fprint (load (ptradd input i)))) + + (ret))) diff --git a/src/backend/tests/c-lisp/turnt.toml b/src/backend/tests/c-lisp/turnt.toml index acf020c..5d75021 100644 --- a/src/backend/tests/c-lisp/turnt.toml +++ b/src/backend/tests/c-lisp/turnt.toml @@ -1 +1 @@ -command = "guile ../../utils/sexp-json.scm < {filename} | python ../../c-lisp.py | python ../../brilisp.py | python ../../llvm.py | bash ../brilisp/run.sh " +command = "guile ../../utils/sexp-json.scm < {filename} | python ../../c-lisp.py | python ../../brilisp.py | python ../../llvm.py | bash ../brilisp/run.sh {args}" From 87ada8e11f031c0337124e9cb530277edbe14ec0 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Fri, 21 Jun 2024 19:50:13 +0530 Subject: [PATCH 06/12] Add test: `insertion-sort` --- src/backend/c-lisp.py | 1 - src/backend/tests/c-lisp/insertion-sort.out | 11 ++++ src/backend/tests/c-lisp/insertion-sort.sexp | 64 ++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/c-lisp/insertion-sort.out create mode 100644 src/backend/tests/c-lisp/insertion-sort.sexp diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index c948fd5..71cd3f7 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -47,7 +47,6 @@ def __init__(self): # Boolean logic "and": "bool", "or": "bool", - "not": "bool", } def c_lisp(self, prog): diff --git a/src/backend/tests/c-lisp/insertion-sort.out b/src/backend/tests/c-lisp/insertion-sort.out new file mode 100644 index 0000000..cd67bc9 --- /dev/null +++ b/src/backend/tests/c-lisp/insertion-sort.out @@ -0,0 +1,11 @@ +-19 +-7 +-5 +-2 +1 +2 +3 +8 +23 +56 +78 diff --git a/src/backend/tests/c-lisp/insertion-sort.sexp b/src/backend/tests/c-lisp/insertion-sort.sexp new file mode 100644 index 0000000..7dd83fc --- /dev/null +++ b/src/backend/tests/c-lisp/insertion-sort.sexp @@ -0,0 +1,64 @@ +;; ARGS: 8 23 1 56 2 -5 -2 78 3 -7 -19 + +(c-lisp + (define ((print int) (n int))) + (define ((atoi int) (s (ptr int)))) + + (define ((swap void) (a (ptr int)) (b (ptr int))) + (declare (tmp int)) + (set tmp (load b)) + (store b (load a)) + (store a tmp) + (ret)) + + (define ((min int) (arr (ptr int)) (n int)) + (declare (i int)) + (declare (idx int)) + + (set idx 0) + (for ((set i 1) + (lt i n) + (set i (add i 1))) + (if (lt (load (ptradd arr i)) (load (ptradd arr idx))) + (set idx i))) + (ret idx)) + + (define ((insertion-sort void) (arr (ptr int)) (len int)) + (declare (min-idx int)) + (declare (i int)) + (declare (rest-arr (ptr int))) + + (for ((set i 0) + (lt i (sub len 1)) + (set i (add i 1))) + (set rest-arr (ptradd arr i)) + (set min-idx (call min rest-arr (sub len i))) + (if (ne min-idx 0) + (call swap + rest-arr + (ptradd rest-arr min-idx)))) + (ret)) + + (define ((main void) (argc int) (argv (ptr (ptr int)))) + (declare (input (ptr int))) + (declare (len int)) + (declare (i int)) + + (set len (sub argc 1)) + (set input (alloc int len)) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (store + (ptradd input i) + (call atoi (load (ptradd argv (add i 1)))))) + + (call insertion-sort input len) + + (for ((set i 0) + (lt i len) + (set i (add i 1))) + (call print (load (ptradd input i)))) + (ret))) + From 79d625993c77738632e5e5fadf32a9247b9c3d71 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 11:43:02 +0530 Subject: [PATCH 07/12] Improve scope naming system --- src/backend/c-lisp.py | 34 +++++++++++++++++++++------------- src/backend/utils/random.py | 11 ++++++----- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index 71cd3f7..47892c2 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -57,11 +57,18 @@ def c_lisp(self, prog): return ["brilisp"] + [self.gen_function(fn) for fn in prog[1:]] def get_scoped_name(self, name): - for scope in self.scopes[::-1]: - scoped_name = f"{name}.{scope}" + scoped_name = name + # Look up nested scopes + for s in range(len(self.scopes), -1, -1): + scope = ".".join(self.scopes[0:s]) + scoped_name = ".".join([scope, name]) if scoped_name in self.symbol_types: return scoped_name - return f"{name}.{self.scopes[-1]}" + # Function's global scope + if name in self.symbol_types: + return name + else: + raise CodegenError(f"Undeclared symbol: {name}") def gen_function(self, func): if not func[0] == "define": @@ -73,19 +80,19 @@ def gen_function(self, func): # Clear the symbol table and scope stack self.symbol_types = {} - self.scopes = [random_label(CLISP_PREFIX, ["scope"])] + self.scopes = [] name, ret_type = func[1][0] parm_types = [] - header = func[1][0:1] for parm in func[1][1:]: - typ = parm[1] - scoped_name = self.get_scoped_name(parm[0]) - parm_types.append(typ) - self.symbol_types[scoped_name] = typ - header.append([scoped_name, typ]) + parm_types.append(parm[1]) + self.symbol_types[parm[0]] = parm[1] self.function_types[name] = [ret_type, parm_types] - return ["define", header, *self.gen_compound_stmt(func[2:], new_scope=False)] + return [ + "define", + func[1], + *self.gen_stmt(func[2:]), + ] def gen_stmt(self, stmt): try: @@ -216,7 +223,8 @@ def gen_decl_stmt(self, stmt): raise CodegenError(f"bad declare statement: {stmt}") name, typ = stmt[1] - scoped_name = f"{name}.{self.scopes[-1]}" + scope = ".".join(self.scopes) + scoped_name = ".".join([scope, name]) if scoped_name in self.symbol_types: raise CodegenError(f"Re-declaration of variable {name}") self.symbol_types[scoped_name] = typ @@ -243,7 +251,7 @@ def is_compound_stmt(self, stmt): def gen_compound_stmt(self, stmt, new_scope=True): if new_scope: - scope = random_label(CLISP_PREFIX, ["scope"]) + scope = random_label() self.scopes.append(scope) instr_list = [] for s in stmt: diff --git a/src/backend/utils/random.py b/src/backend/utils/random.py index 086942f..1337c91 100644 --- a/src/backend/utils/random.py +++ b/src/backend/utils/random.py @@ -7,8 +7,9 @@ def random_label(prefix="", extra_prefixes=[], length=10): Return a random string. If prefix and extra_prefix are given, they will be used as prefixes to the random string. """ - return ( - ".".join([prefix, *extra_prefixes]) - + "." - + "".join([random.choice(string.ascii_lowercase) for i in range(length)]) - ) + prefixes = ".".join([prefix, *extra_prefixes]) + suffix = "".join([random.choice(string.ascii_lowercase) for i in range(length)]) + if prefixes: + return f"{prefixes}.{suffix}" + else: + return suffix From 4dbc3876631cf8dc3911474d69b319b2ab2d5210 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 11:58:54 +0530 Subject: [PATCH 08/12] Scope temporary variables --- src/backend/c-lisp.py | 22 +++++++++++----------- src/backend/utils/random.py | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index 47892c2..b3ebe79 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -127,7 +127,7 @@ def gen_while_stmt(self, stmt): raise CodegenError(f"Bad while statement: {stmt}") cond_sym, loop_lbl, cont_lbl, break_lbl = [ - random_label(CLISP_PREFIX, [extra]) + random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ( "cond", "loop", @@ -156,7 +156,7 @@ def gen_for_stmt(self, stmt): raise CodegenError(f"Bad for statement: {stmt}") cond_sym, loop_lbl, cont_lbl, break_lbl = [ - random_label(CLISP_PREFIX, [extra]) + random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ( "cond", "loop", @@ -186,7 +186,7 @@ def is_if_stmt(self, stmt): def gen_if_stmt(self, stmt): cond_sym, true_lbl, false_lbl, out_lbl = [ - random_label(CLISP_PREFIX, [extra]) + random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ( "cond", "lbl_true", @@ -237,7 +237,7 @@ def gen_ret_stmt(self, stmt): if len(stmt) == 1: return [["ret"]] elif len(stmt) == 2: - res_sym = random_label(CLISP_PREFIX) + res_sym = random_label(CLISP_PREFIX, self.scopes) instr_list = self.gen_expr(stmt[1], res_sym=res_sym) instr_list.append(["ret", res_sym]) return instr_list @@ -298,7 +298,7 @@ def gen_call_expr(self, expr, res_sym): instr_list = [] arg_syms = [] for arg in expr[2:]: - arg_sym = random_label(CLISP_PREFIX) + arg_sym = random_label(CLISP_PREFIX, self.scopes) arg_syms.append(arg_sym) instr_list += self.gen_expr(arg, res_sym=arg_sym) name = expr[1] @@ -332,7 +332,7 @@ def gen_binary_expr(self, expr, res_sym): instr_list = [] in1_sym, in2_sym = [ - random_label(CLISP_PREFIX, [extra]) for extra in ("in1", "in2") + random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ("in1", "in2") ] opcode = expr[0] typ = self.binary_op_types[opcode] @@ -349,7 +349,7 @@ def gen_ptradd_expr(self, expr, res_sym): if len(expr) != 3: raise CodegenError(f"Bad ptradd expression: {expr}") - offset_sym = random_label("tmp_clisp") + offset_sym = random_label(CLISP_PREFIX, self.scopes) ptr_name = self.get_scoped_name(expr[1]) ptr_type = self.symbol_types[ptr_name] self.pointer_types[res_sym] = ptr_type @@ -365,7 +365,7 @@ def gen_load_expr(self, expr, res_sym): if len(expr) != 2: raise CodegenError(f"Bad load expression: {expr}") - ptr_sym = random_label("tmp_clisp") + ptr_sym = random_label(CLISP_PREFIX, self.scopes) return [ *self.gen_expr(expr[1], res_sym=ptr_sym), ["set", [res_sym, self.pointer_types[ptr_sym][1]], ["load", ptr_sym]], @@ -379,7 +379,7 @@ def gen_store_expr(self, expr, res_sym): raise CodegenError(f"Bad store expression: {expr}") val_sym, ptr_sym = [ - random_label(CLISP_PREFIX, [extra]) for extra in ("val", "ptr") + random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ("val", "ptr") ] return [ *self.gen_expr(expr[1], res_sym=ptr_sym), @@ -397,14 +397,14 @@ def gen_alloc_expr(self, expr, res_sym): ptr_type = ["ptr", expr[1]] self.pointer_types[res_sym] = ptr_type - size_sym = random_label(CLISP_PREFIX) + size_sym = random_label(CLISP_PREFIX, self.scopes) return [ *self.gen_expr(expr[2], res_sym=size_sym), ["set", [res_sym, ptr_type], ["alloc", size_sym]], ] def gen_expr(self, expr, res_sym=None): - res_sym = res_sym or random_label(CLISP_PREFIX) + res_sym = res_sym or random_label(CLISP_PREFIX, self.scopes) if self.is_literal_expr(expr): return self.gen_literal_expr(expr, res_sym) elif self.is_set_expr(expr): diff --git a/src/backend/utils/random.py b/src/backend/utils/random.py index 1337c91..465590f 100644 --- a/src/backend/utils/random.py +++ b/src/backend/utils/random.py @@ -7,7 +7,7 @@ def random_label(prefix="", extra_prefixes=[], length=10): Return a random string. If prefix and extra_prefix are given, they will be used as prefixes to the random string. """ - prefixes = ".".join([prefix, *extra_prefixes]) + prefixes = ".".join([*extra_prefixes, prefix]) suffix = "".join([random.choice(string.ascii_lowercase) for i in range(length)]) if prefixes: return f"{prefixes}.{suffix}" From 7e8a1dd420bfbd01cc156f7f98729cec835ed334 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 12:05:54 +0530 Subject: [PATCH 09/12] Minor tweaks --- src/backend/c-lisp.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index b3ebe79..30690eb 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -56,7 +56,7 @@ def c_lisp(self, prog): return ["brilisp"] + [self.gen_function(fn) for fn in prog[1:]] - def get_scoped_name(self, name): + def scope_lookup(self, name): scoped_name = name # Look up nested scopes for s in range(len(self.scopes), -1, -1): @@ -91,7 +91,7 @@ def gen_function(self, func): return [ "define", func[1], - *self.gen_stmt(func[2:]), + *self.gen_compound_stmt(func[2:], new_scope = False), ] def gen_stmt(self, stmt): @@ -223,8 +223,7 @@ def gen_decl_stmt(self, stmt): raise CodegenError(f"bad declare statement: {stmt}") name, typ = stmt[1] - scope = ".".join(self.scopes) - scoped_name = ".".join([scope, name]) + scoped_name = ".".join([*self.scopes, name]) if scoped_name in self.symbol_types: raise CodegenError(f"Re-declaration of variable {name}") self.symbol_types[scoped_name] = typ @@ -265,7 +264,7 @@ def is_set_expr(self, expr): def gen_set_expr(self, expr, res_sym): name = expr[1] - scoped_name = self.get_scoped_name(name) + scoped_name = self.scope_lookup(name) if not scoped_name in self.symbol_types: raise CodegenError(f"Cannot set undeclared variable: {name}") @@ -311,7 +310,7 @@ def is_var_expr(self, expr): return isinstance(expr, str) def gen_var_expr(self, expr, res_sym): - scoped_name = self.get_scoped_name(expr) + scoped_name = self.scope_lookup(expr) if scoped_name in self.symbol_types: typ = self.symbol_types[scoped_name] instr_list = [ @@ -350,7 +349,7 @@ def gen_ptradd_expr(self, expr, res_sym): raise CodegenError(f"Bad ptradd expression: {expr}") offset_sym = random_label(CLISP_PREFIX, self.scopes) - ptr_name = self.get_scoped_name(expr[1]) + ptr_name = self.scope_lookup(expr[1]) ptr_type = self.symbol_types[ptr_name] self.pointer_types[res_sym] = ptr_type return [ From 5f0c501c05c9e32b110681a5b3a4536c214bc696 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 12:25:48 +0530 Subject: [PATCH 10/12] Implement `not` --- src/backend/c-lisp.py | 76 ++++++++++---------- src/backend/tests/c-lisp/insertion-sort.sexp | 2 +- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index 30690eb..e915d90 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -18,35 +18,36 @@ def __init__(self): self.function_types = {} # Function name > (ret-type, (arg-types...)) self.pointer_types = {} # For internal use, e.g. temporary pointer variables - self.binary_op_types = { + self.fixed_op_types = { # : # Integer arithmetic - "add": "int", - "sub": "int", - "mul": "int", - "div": "int", + "add": ("int", 2), + "sub": ("int", 2), + "mul": ("int", 2), + "div": ("int", 2), # Integer comparison - "eq": "bool", - "ne": "bool", - "lt": "bool", - "gt": "bool", - "le": "bool", - "ge": "bool", + "eq": ("bool", 2), + "ne": ("bool", 2), + "lt": ("bool", 2), + "gt": ("bool", 2), + "le": ("bool", 2), + "ge": ("bool", 2), # Floating-point arithmetic - "fadd": "float", - "fsub": "float", - "fmul": "float", - "fdiv": "float", + "fadd": ("float", 2), + "fsub": ("float", 2), + "fmul": ("float", 2), + "fdiv": ("float", 2), # Floating-point comparison - "feq": "bool", - "fne": "bool", - "flt": "bool", - "fgt": "bool", - "fle": "bool", - "fge": "bool", + "feq": ("bool", 2), + "fne": ("bool", 2), + "flt": ("bool", 2), + "fgt": ("bool", 2), + "fle": ("bool", 2), + "fge": ("bool", 2), # Boolean logic - "and": "bool", - "or": "bool", + "and": ("bool", 2), + "or": ("bool", 2), + "not": ("bool", 1), } def c_lisp(self, prog): @@ -322,23 +323,22 @@ def gen_var_expr(self, expr, res_sym): else: raise CodegenError(f"Reference to undeclared variable: {expr}") - def is_binary_expr(self, expr): - return expr[0] in self.binary_op_types - - def gen_binary_expr(self, expr, res_sym): - if not len(expr) == 3: - raise CodegenError(f"Binary operation takes only 2 operands: {expr}") + def is_fixed_type_expr(self, expr): + return expr[0] in self.fixed_op_types + def gen_fixed_type_expr(self, expr, res_sym): instr_list = [] - in1_sym, in2_sym = [ - random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ("in1", "in2") - ] opcode = expr[0] - typ = self.binary_op_types[opcode] + typ, n_ops = self.fixed_op_types[opcode] + if not (len(expr) == n_ops + 1): + raise CodegenError(f"`{opcode}` takes only 2 operands: {expr}") + in_syms = [random_label(CLISP_PREFIX, [*self.scopes, f"in{n}"]) for n in range(n_ops)] + input_instrs = [] + for n in range(n_ops): + input_instrs += [*self.gen_expr(expr[n+1], in_syms[n])] return [ - *self.gen_expr(expr[1], in1_sym), - *self.gen_expr(expr[2], in2_sym), - ["set", [res_sym, typ], [opcode, in1_sym, in2_sym]], + *input_instrs, + ["set", [res_sym, typ], [opcode, *in_syms]], ] def is_ptradd_expr(self, expr): @@ -412,8 +412,8 @@ def gen_expr(self, expr, res_sym=None): return self.gen_call_expr(expr, res_sym) elif self.is_var_expr(expr): return self.gen_var_expr(expr, res_sym) - elif self.is_binary_expr(expr): - return self.gen_binary_expr(expr, res_sym) + elif self.is_fixed_type_expr(expr): + return self.gen_fixed_type_expr(expr, res_sym) elif self.is_ptradd_expr(expr): return self.gen_ptradd_expr(expr, res_sym) elif self.is_load_expr(expr): diff --git a/src/backend/tests/c-lisp/insertion-sort.sexp b/src/backend/tests/c-lisp/insertion-sort.sexp index 7dd83fc..8af8e6c 100644 --- a/src/backend/tests/c-lisp/insertion-sort.sexp +++ b/src/backend/tests/c-lisp/insertion-sort.sexp @@ -33,7 +33,7 @@ (set i (add i 1))) (set rest-arr (ptradd arr i)) (set min-idx (call min rest-arr (sub len i))) - (if (ne min-idx 0) + (if (not (eq min-idx 0)) (call swap rest-arr (ptradd rest-arr min-idx)))) From 869833c1ff01704b5a56514272447a534a17dc08 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 13:31:11 +0530 Subject: [PATCH 11/12] Do not scope temporary variables Co-Authored by: Sasank --- src/backend/brilisp.py | 9 +++--- src/backend/c-lisp.py | 59 ++++++++++++++++++------------------- src/backend/utils/random.py | 6 ++-- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/backend/brilisp.py b/src/backend/brilisp.py index 47c6da0..2309128 100644 --- a/src/backend/brilisp.py +++ b/src/backend/brilisp.py @@ -158,15 +158,16 @@ def gen_store_instr(instr): def brilisp(expr): - for x in expr: + assert expr[0] == "brilisp" + body = expr[1:] + for x in body: assert is_function(x), f"{x} is not a function" - return {"functions": [gen_function(x) for x in expr]} + return {"functions": [gen_function(x) for x in body]} def main(): expr = json.load(sys.stdin) - assert expr[0] == "brilisp" - print(json.dumps(brilisp(expr[1:]))) + print(json.dumps(brilisp(expr))) if __name__ == "__main__": diff --git a/src/backend/c-lisp.py b/src/backend/c-lisp.py index e915d90..6f69e57 100755 --- a/src/backend/c-lisp.py +++ b/src/backend/c-lisp.py @@ -57,19 +57,17 @@ def c_lisp(self, prog): return ["brilisp"] + [self.gen_function(fn) for fn in prog[1:]] - def scope_lookup(self, name): - scoped_name = name - # Look up nested scopes + def construct_scoped_name(self, name, scopes): + return ".".join([name] + scopes) + + def scoped_lookup(self, name): + """Look up the name in reverse order of current scope stack""" + # be as specific as possible first for s in range(len(self.scopes), -1, -1): - scope = ".".join(self.scopes[0:s]) - scoped_name = ".".join([scope, name]) + scoped_name = self.construct_scoped_name(name, self.scopes[:s]) if scoped_name in self.symbol_types: return scoped_name - # Function's global scope - if name in self.symbol_types: - return name - else: - raise CodegenError(f"Undeclared symbol: {name}") + raise CodegenError(f"Undeclared symbol: {name}") def gen_function(self, func): if not func[0] == "define": @@ -92,7 +90,7 @@ def gen_function(self, func): return [ "define", func[1], - *self.gen_compound_stmt(func[2:], new_scope = False), + *self.gen_compound_stmt(func[2:], new_scope=False), ] def gen_stmt(self, stmt): @@ -128,7 +126,7 @@ def gen_while_stmt(self, stmt): raise CodegenError(f"Bad while statement: {stmt}") cond_sym, loop_lbl, cont_lbl, break_lbl = [ - random_label(CLISP_PREFIX, [*self.scopes, extra]) + random_label(CLISP_PREFIX, [extra]) for extra in ( "cond", "loop", @@ -157,7 +155,7 @@ def gen_for_stmt(self, stmt): raise CodegenError(f"Bad for statement: {stmt}") cond_sym, loop_lbl, cont_lbl, break_lbl = [ - random_label(CLISP_PREFIX, [*self.scopes, extra]) + random_label(CLISP_PREFIX, [extra]) for extra in ( "cond", "loop", @@ -187,7 +185,7 @@ def is_if_stmt(self, stmt): def gen_if_stmt(self, stmt): cond_sym, true_lbl, false_lbl, out_lbl = [ - random_label(CLISP_PREFIX, [*self.scopes, extra]) + random_label(CLISP_PREFIX, [extra]) for extra in ( "cond", "lbl_true", @@ -224,7 +222,7 @@ def gen_decl_stmt(self, stmt): raise CodegenError(f"bad declare statement: {stmt}") name, typ = stmt[1] - scoped_name = ".".join([*self.scopes, name]) + scoped_name = self.construct_scoped_name(name, self.scopes) if scoped_name in self.symbol_types: raise CodegenError(f"Re-declaration of variable {name}") self.symbol_types[scoped_name] = typ @@ -237,7 +235,7 @@ def gen_ret_stmt(self, stmt): if len(stmt) == 1: return [["ret"]] elif len(stmt) == 2: - res_sym = random_label(CLISP_PREFIX, self.scopes) + res_sym = random_label(CLISP_PREFIX) instr_list = self.gen_expr(stmt[1], res_sym=res_sym) instr_list.append(["ret", res_sym]) return instr_list @@ -265,7 +263,7 @@ def is_set_expr(self, expr): def gen_set_expr(self, expr, res_sym): name = expr[1] - scoped_name = self.scope_lookup(name) + scoped_name = self.scoped_lookup(name) if not scoped_name in self.symbol_types: raise CodegenError(f"Cannot set undeclared variable: {name}") @@ -298,7 +296,7 @@ def gen_call_expr(self, expr, res_sym): instr_list = [] arg_syms = [] for arg in expr[2:]: - arg_sym = random_label(CLISP_PREFIX, self.scopes) + arg_sym = random_label(CLISP_PREFIX) arg_syms.append(arg_sym) instr_list += self.gen_expr(arg, res_sym=arg_sym) name = expr[1] @@ -311,12 +309,10 @@ def is_var_expr(self, expr): return isinstance(expr, str) def gen_var_expr(self, expr, res_sym): - scoped_name = self.scope_lookup(expr) + scoped_name = self.scoped_lookup(expr) if scoped_name in self.symbol_types: typ = self.symbol_types[scoped_name] - instr_list = [ - ["set", [res_sym, typ], ["id", scoped_name]] - ] + instr_list = [["set", [res_sym, typ], ["id", scoped_name]]] if typ[0] == "ptr": self.pointer_types[res_sym] = typ return instr_list @@ -332,10 +328,12 @@ def gen_fixed_type_expr(self, expr, res_sym): typ, n_ops = self.fixed_op_types[opcode] if not (len(expr) == n_ops + 1): raise CodegenError(f"`{opcode}` takes only 2 operands: {expr}") - in_syms = [random_label(CLISP_PREFIX, [*self.scopes, f"in{n}"]) for n in range(n_ops)] + in_syms = [ + random_label(CLISP_PREFIX, [f"inp_{n}"]) for n in range(n_ops) + ] input_instrs = [] for n in range(n_ops): - input_instrs += [*self.gen_expr(expr[n+1], in_syms[n])] + input_instrs += [*self.gen_expr(expr[n + 1], in_syms[n])] return [ *input_instrs, ["set", [res_sym, typ], [opcode, *in_syms]], @@ -348,8 +346,8 @@ def gen_ptradd_expr(self, expr, res_sym): if len(expr) != 3: raise CodegenError(f"Bad ptradd expression: {expr}") - offset_sym = random_label(CLISP_PREFIX, self.scopes) - ptr_name = self.scope_lookup(expr[1]) + offset_sym = random_label(CLISP_PREFIX) + ptr_name = self.scoped_lookup(expr[1]) ptr_type = self.symbol_types[ptr_name] self.pointer_types[res_sym] = ptr_type return [ @@ -364,7 +362,7 @@ def gen_load_expr(self, expr, res_sym): if len(expr) != 2: raise CodegenError(f"Bad load expression: {expr}") - ptr_sym = random_label(CLISP_PREFIX, self.scopes) + ptr_sym = random_label(CLISP_PREFIX) return [ *self.gen_expr(expr[1], res_sym=ptr_sym), ["set", [res_sym, self.pointer_types[ptr_sym][1]], ["load", ptr_sym]], @@ -378,7 +376,8 @@ def gen_store_expr(self, expr, res_sym): raise CodegenError(f"Bad store expression: {expr}") val_sym, ptr_sym = [ - random_label(CLISP_PREFIX, [*self.scopes, extra]) for extra in ("val", "ptr") + random_label(CLISP_PREFIX, [extra]) + for extra in ("val", "ptr") ] return [ *self.gen_expr(expr[1], res_sym=ptr_sym), @@ -396,14 +395,14 @@ def gen_alloc_expr(self, expr, res_sym): ptr_type = ["ptr", expr[1]] self.pointer_types[res_sym] = ptr_type - size_sym = random_label(CLISP_PREFIX, self.scopes) + size_sym = random_label(CLISP_PREFIX) return [ *self.gen_expr(expr[2], res_sym=size_sym), ["set", [res_sym, ptr_type], ["alloc", size_sym]], ] def gen_expr(self, expr, res_sym=None): - res_sym = res_sym or random_label(CLISP_PREFIX, self.scopes) + res_sym = res_sym or random_label(CLISP_PREFIX) if self.is_literal_expr(expr): return self.gen_literal_expr(expr, res_sym) elif self.is_set_expr(expr): diff --git a/src/backend/utils/random.py b/src/backend/utils/random.py index 465590f..5958317 100644 --- a/src/backend/utils/random.py +++ b/src/backend/utils/random.py @@ -2,14 +2,14 @@ import string -def random_label(prefix="", extra_prefixes=[], length=10): +def random_label(prefix="", extra_prefixes=[], length=8): """ Return a random string. If prefix and extra_prefix are given, they will be used as prefixes to the random string. """ - prefixes = ".".join([*extra_prefixes, prefix]) + prefixes = ".".join([prefix, *extra_prefixes]) suffix = "".join([random.choice(string.ascii_lowercase) for i in range(length)]) if prefixes: - return f"{prefixes}.{suffix}" + return f"{prefixes}-{suffix}" else: return suffix From 86e2bd663fc5e73b48f896cba932e8b813517832 Mon Sep 17 00:00:00 2001 From: Vedanth Padmaraman Date: Mon, 24 Jun 2024 14:04:44 +0530 Subject: [PATCH 12/12] Refactor tests --- src/backend/tests/c-lisp/array-sum.sexp | 2 +- src/backend/tests/c-lisp/gaussian-elimination.sexp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/tests/c-lisp/array-sum.sexp b/src/backend/tests/c-lisp/array-sum.sexp index 236f73d..a21b213 100644 --- a/src/backend/tests/c-lisp/array-sum.sexp +++ b/src/backend/tests/c-lisp/array-sum.sexp @@ -16,7 +16,6 @@ (declare (arr1 (ptr int))) (declare (arr2 (ptr int))) (declare (i int)) - (declare (arr_i (ptr int))) (set arr1 (alloc int 10)) (set arr2 (alloc int 10)) @@ -24,6 +23,7 @@ (for ((set i 0) (lt i 10) (set i (add i 1))) + (declare (arr_i (ptr int))) (set arr_i (ptradd arr1 i)) (store arr_i i) (set arr_i (ptradd arr2 i)) diff --git a/src/backend/tests/c-lisp/gaussian-elimination.sexp b/src/backend/tests/c-lisp/gaussian-elimination.sexp index ba5fb61..8533139 100644 --- a/src/backend/tests/c-lisp/gaussian-elimination.sexp +++ b/src/backend/tests/c-lisp/gaussian-elimination.sexp @@ -2,7 +2,6 @@ (c-lisp (define ((print int) (n int))) (define ((fprint float) (n float))) - (define ((index int) (i int) (j int) (ncols int))) (define ((strtof float) (s (ptr int)) (end int))) (define ((atoi int) (s (ptr int))))