Browse Source

generate function calls

Johan Rong 2 ngày trước cách đây
mục cha
commit
b38033bb2e

+ 5 - 1
examples/testing/src/main.zk

@@ -10,8 +10,12 @@
     )
 }
 
+fn test(x: i64) -> i64 {
+    return 6 + x
+}
+
 fn main() -> void {
-    val test: i64 = 123 * 2
+    val test: i64 = test(12)
     #print_i64(test)
     #print_i64(test + 1)
     return

+ 2 - 2
src/zelkelc/ast/parser.py

@@ -305,7 +305,7 @@ class Parser:
             irname = "zkmain"
 
         return types.FunctionDeclaration(
-            name=name, typ=typ, args=args, body=body, irname=irname
+            name, typ, args, body, irname
         )
 
     def parse_return(self) -> types.ReturnStatement:
@@ -389,7 +389,7 @@ class Parser:
 
                     self.expect(token.RParen())
                     return types.PrimaryExpression(
-                        types.FunctionCall(t.value, args, None), types.FunctionCall
+                        types.FunctionCall(t.value, None, None, args), types.FunctionCall
                     )
                 else:
                     return types.PrimaryExpression(

+ 1 - 0
src/zelkelc/ast/types.py

@@ -163,6 +163,7 @@ class VariableRef:
 class FunctionCall:
     name: str
     irname: str
+    typ: Value
     args: list[Expression]
 
 

+ 20 - 0
src/zelkelc/codegen/codegen.py

@@ -2,6 +2,7 @@ import sys
 
 from src.zelkelc.ast import types
 from src.zelkelc.expander.expander import render_llvm
+from src.zelkelc.ast.parser import Parser
 
 
 class IRTable:
@@ -203,6 +204,20 @@ class Codegen:
                 print(f"Cannot do operation '{sign}' on f64")
                 sys.exit(1)
 
+    def get_function_args_llvm(self, node: types.FunctionCall) -> tuple[str, str]:
+        print(node.args)
+
+        ir = ""
+        args_str = ""
+        for i, arg in enumerate(node.args):
+            if i != 0:
+                args_str += ", "
+            count, arg_ir = self.gen_expression(arg)
+            ir += arg_ir
+            args_str += f"{arg.typ.to_llvm()} %{count}"
+            
+        return ir, args_str
+
     def gen_expression(self, node: types.Expression) -> tuple[str, str]:
         ir = ""
 
@@ -251,6 +266,11 @@ class Codegen:
                         self.temp_counter += 1
                     case types.VariableRef:
                         return node.value.irname, ir
+                    case types.FunctionCall:
+                        args_ir, args_str = self.get_function_args_llvm(node.value)
+                        ir += args_ir
+                        ir += f"\n%{self.temp_counter} = call {Parser.type_to_str(node.value.typ, True)} @{node.value.irname}({args_str})"
+                        self.temp_counter += 1
                     case _:
                         print(
                             f"gen_expression() for PrimaryExpression for {type(node.value)}"

+ 13 - 9
src/zelkelc/validator/scope.py

@@ -39,7 +39,7 @@ class ValueSignature:
     name: str
     irname: str
     mutable: bool
-    typ: type[types.Integer64] | type[types.String] | type[types.Void]
+    typ: type[types.Integer64] | type[types.Float64] | type[types.String] | type[types.Void]
 
 
 @dataclass
@@ -78,8 +78,8 @@ class Scope:
             values={},
         )
 
-    def resolve_variable(self, name: str) -> Optional[ValueSignature]:
-        current: Optional[Scope] = self
+    def resolve_variable(self, name: str) -> ValueSignature | None:
+        current: Scope | None = self
         while current is not None:
             if name in current.values:
                 return current.values[name]
@@ -88,8 +88,8 @@ class Scope:
 
     def resolve_function(
         self, scope_checker: ScopeChecker, name: str, args: list[types.Expression]
-    ) -> Optional[FunctionSignature]:
-        current: Optional[Scope] = self
+    ) -> FunctionSignature | None:
+        current: Scope | None = self
         while current is not None:
             overloads = current.functions.get(name)
             if overloads:
@@ -103,8 +103,8 @@ class Scope:
 
     def resolve_function_by_types(
         self, name: str, arg_types: list[types.Value]
-    ) -> Optional[FunctionSignature]:
-        current: Optional[Scope] = self
+    ) -> FunctionSignature | None:
+        current: Scope | None = self
         while current is not None:
             overloads = current.functions.get(name)
             if overloads:
@@ -116,8 +116,11 @@ class Scope:
 
     def expr_args_to_arg_types(
         self, scope_checker: ScopeChecker, args: list[types.Expression]
-    ) -> Optional[list[types.Value]]:
+    ) -> list[types.Value] | None:
         arg_types: list[types.Value] = []
+        if args is None:
+            return []
+        
         for arg in args:
             typ = scope_checker._infer_expression_type(arg, self)
             if typ is None:
@@ -397,7 +400,7 @@ class ScopeChecker:
                 expr.value.irname = signature.irname
                 expr.value.typ = signature.typ
                 return signature.typ
-            case types.PrimaryExpression(types.FunctionCall(name, args)):
+            case types.PrimaryExpression(types.FunctionCall(name, _, _, args)):
                 arg_types = active_scope.expr_args_to_arg_types(self, args)
                 if arg_types is None:
                     self._error("Could not get argument types from function call")
@@ -411,6 +414,7 @@ class ScopeChecker:
                     return None
 
                 expr.value.irname = signature.irname
+                expr.value.typ = signature.typ
                 return signature.typ
             case types.UnaryExpression(inner_expr, sign):
                 inner_type = self._infer_expression_type(inner_expr, active_scope)