Browse Source

self argument, idk about class paths, etc

Johan Rong 9 giờ trước cách đây
mục cha
commit
c1af0a9e2b

+ 2 - 2
README.md

@@ -26,7 +26,7 @@ Lexer --> Preprocessor (unimplemented) --> Parser --> Expander --> Validator -->
 ```
 
 ### Just a bunch of stuff
-```kotlin
+```rust
 class Parser {
   val tokens: Arr<Token>
   val cursor: Int
@@ -41,7 +41,7 @@ class Parser {
 fn main() -> i64 {
   val parser: Parser = Parser::new(etcetc...) // with hooked constructor, also puts reference counting
   
-  val parser_manually: &Parser = mem.alloc(mem.sizeof(Parser)) // will not be tracked by reference counter, the pointer address is not added to the GC's pointer track list. GC only counts addresses in it's list
+  val parser_manually: Parser = mem.alloc(mem.sizeof(Parser)) // will not be tracked by reference counter, the pointer address is not added to the GC's pointer track list. GC only counts addresses in it's list
   *parser_manually.tokens = ...
   *parser_manually.cursor = ...
 

+ 5 - 18
examples/test/src/main.zk

@@ -1,24 +1,11 @@
-#llvm(
-    #"@int.fmt = private unnamed_addr constant [14 x i8] c"Integer: %ld\0A\00""#
-)
-#llvm("declare i32 @printf(ptr, ...)")
+class MyClass {
+    val prop: i64
 
-#fn print_i64($x: expr) {
-    #llvm(
-        "%call.{:id} = call i32 (ptr, ...) @printf(ptr @int.fmt, {0:ty} {0})",
-        $x
-    )
-}
-
-fn add(a: i64, b: i64) -> i64 {
-    return a + b
+    fn new(self, prop: i64) :constr -> void {
+        self.prop = prop
+    }
 }
 
 fn main() -> void {
-    var test: i64 = add(5, 5)
-    test += 5 + 2 * 4 + (2+3 * 4+1)
-
-    #print_i64(test)
-    #print_i64(test + 1)
     return
 }

+ 14 - 6
src/zelkelc/ast/parser.py

@@ -285,9 +285,12 @@ class Parser:
         while self.cursor < len(self.tokens) and not self.current(token.RParen()):
             arg_name = self.expect_type(token.Identifier).value
 
-            self.expect(token.Colon())
-            typ = self.parse_type(False)
-            args[arg_name] = typ
+            if arg_name == "self":
+                args[arg_name] = None
+            else:
+                self.expect(token.Colon())
+                typ = self.parse_type(False)
+                args[arg_name] = typ
 
             if not self.current(token.Comma()):
                 break
@@ -295,7 +298,12 @@ class Parser:
                 self.expect(token.Comma())
 
         self.expect(token.RParen())
-
+        
+        label = None
+        if self.current(token.Colon()):
+            self.expect(token.Colon())
+            label = self.expect_type(token.Identifier)
+            
         self.expect(token.Arrow())
         typ = self.parse_type(True)
 
@@ -307,7 +315,7 @@ class Parser:
         if name == "main":
             irname = "zkmain"
 
-        return types.FunctionDeclaration(name, typ, args, body, irname)
+        return types.FunctionDeclaration(name, label, typ, args, body, irname)
 
     def parse_return(self) -> types.ReturnStatement:
         self.expect(token.Identifier("return"))
@@ -340,7 +348,7 @@ class Parser:
     def parse_value_assignment(self) -> types.ValueAssignment:
         name = self.expect_type(token.Identifier).value
 
-        assigner = self.tokens[self.cursor].value
+        assigner = self.expect_type(token.Assigner).value
         match assigner:
             case "=":
                 self.expect(token.Assigner("="))

+ 8 - 21
src/zelkelc/ast/types.py

@@ -41,6 +41,7 @@ class ValueDeclaration:
 @dataclass
 class FunctionDeclaration:
     name: str
+    label: str | None
     typ: Value
     args: dict[str, Value]
     body: list[Node]
@@ -120,9 +121,6 @@ Expression = BinaryExpression | UnaryExpression | PrimaryExpression
 class Integer64:
     value: int
 
-    def to_llvm() -> str:
-        return "i64"
-
     def __eq__(self, other):
         if not isinstance(other, Integer64):
             return False
@@ -133,9 +131,6 @@ class Integer64:
 class Float64:
     value: int
 
-    def to_llvm() -> str:
-        return "double"
-
     def __eq__(self, other):
         if not isinstance(other, Float64):
             return False
@@ -146,10 +141,6 @@ class Float64:
 class String:
     value: str
 
-    def to_llvm() -> str:
-        print("Cannot convert String to llvm ir")
-        sys.exit(1)
-
 
 @dataclass
 class Void:
@@ -157,6 +148,12 @@ class Void:
         return "void"
 
 
+@dataclass
+class Class:
+    name: str
+    irname: str
+
+
 @dataclass
 class VariableRef:
     name: str
@@ -177,14 +174,4 @@ class FunctionCall:
     args: list[Expression]
 
 
-@dataclass
-class Ptr[T]:
-    pass
-
-
-@dataclass
-class Val[T]:
-    pass
-
-
-Value = Integer64 | Float64 | String | Void | VariableRef | FunctionCall
+Value = Class | Integer64 | Float64 | String | Void | VariableRef | FunctionCall

+ 7 - 5
src/zelkelc/codegen/codegen.py

@@ -92,14 +92,14 @@ class Codegen:
     def gen_struct_declaration(self, node: types.StructDeclaration):
         members_str = ""
         for i, m in enumerate(node.members):
-            members_str += f"{', ' if i != 0 else ''}{m.typ.to_llvm()}"
+            members_str += f"{', ' if i != 0 else ''}{self.llvm_type(m.typ)}"
 
         self.ir.structs += f"\n%{node.irname} = type " + "{ " + members_str + " }"
 
     def gen_class_declaration(self, node: types.ClassDeclaration):
         members_str = ""
         for i, m in enumerate(node.members):
-            members_str += f"{', ' if i != 0 else ''}{m.typ.to_llvm()}"
+            members_str += f"{', ' if i != 0 else ''}{self.llvm_type(m.typ)}"
 
         self.ir.structs += f"\n%{node.irname} = type " + "{ " + members_str + " }"
 
@@ -109,9 +109,9 @@ class Codegen:
     def gen_function_declaration(self, node: types.FunctionDeclaration) -> str:
         args_str = ""
         for i, (name, typ) in enumerate(node.args.items()):
-            args_str += f"{', ' if i != 0 else ''}{typ.to_llvm()} %{name}"
+            args_str += f"{', ' if i != 0 else ''}{self.llvm_type(typ)} %{name}"
 
-        ir = f"\ndefine {node.typ.to_llvm()!s} @{node.irname}({args_str}) " + "{"
+        ir = f"\ndefine {self.llvm_type(node.typ)} @{node.irname}({args_str}) " + "{"
         ir += "\nentry:"
 
         for child_node in node.body:
@@ -226,13 +226,15 @@ class Codegen:
         return ir, args_str
 
     @staticmethod
-    def llvm_type(typ) -> str:
+    def llvm_type(typ: types.Value) -> str:
         if typ is types.Integer64 or isinstance(typ, types.Integer64):
             return "i64"
         if typ is types.Float64 or isinstance(typ, types.Float64):
             return "double"
         if typ is types.Void or isinstance(typ, types.Void):
             return "void"
+        if typ is types.Class or isinstance(typ, types.Class):
+            return f"%{typ.irname}*"
         raise GeneratorError(
             f"Cannot convert type {typ} to llvm ir (was the AST validated?)"
         )

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

@@ -1,8 +1,8 @@
 from __future__ import annotations
 
-import src.zelkelc.ast.types as types
 from dataclasses import dataclass
-from typing import Optional
+
+from src.zelkelc.ast import types
 
 
 @dataclass
@@ -28,6 +28,7 @@ class ClassSignature:
 @dataclass
 class FunctionSignature:
     name: str
+    label: str | None
     irname: str
     static: bool
     typ: types.Value
@@ -39,12 +40,7 @@ class ValueSignature:
     name: str
     irname: str
     mutable: bool
-    typ: (
-        type[types.Integer64]
-        | type[types.Float64]
-        | type[types.String]
-        | type[types.Void]
-    )
+    typ: type[types.Integer64 | types.Float64 | types.String | types.Void]
 
 
 @dataclass
@@ -52,13 +48,13 @@ class MemberSignature:
     name: str
     irname: str
     mutable: bool
-    typ: type[types.Integer64] | type[types.String] | type[types.Void]
+    typ: type[types.Integer64 | types.String | types.Void]
     member_idx: int
 
 
 @dataclass
 class Scope:
-    parent: Optional[Scope]
+    parent: Scope | None
     classes: dict[str, ClassSignature]
     structs: dict[str, StructSignature]
     functions: dict[str, list[FunctionSignature]]
@@ -224,8 +220,12 @@ class ScopeChecker:
 
                     method_table: dict[str, list[FunctionSignature]] = {}
                     for method in methods:
+                        if "self" in method.args:
+                            method.args["self"] = types.Class(name, irname)
+
                         signature = FunctionSignature(
                             name=method.name,
+                            label=method.label,
                             irname=method.irname,
                             static=False,
                             typ=method.typ,
@@ -254,7 +254,7 @@ class ScopeChecker:
                         methods=method_table,
                     )
 
-                case types.FunctionDeclaration(name, typ, args, _, irname):
+                case types.FunctionDeclaration(name, label, typ, args, _, irname):
                     existing = self.global_scope.resolve_function_by_types(
                         name, list(args.values())
                     )
@@ -263,10 +263,11 @@ class ScopeChecker:
                             f"Function '{name}' is already defined with following signature '{existing}'"
                         )
                         continue
-
+                    
                     self.global_scope._ensure_function_overloads(name).append(
                         FunctionSignature(
                             name=name,
+                            label=label,
                             irname=irname,
                             static=True,
                             typ=typ,