diff --git a/examples/methods.bux b/examples/methods.bux new file mode 100644 index 0000000..544642f --- /dev/null +++ b/examples/methods.bux @@ -0,0 +1,38 @@ +// Methods - Struct with methods using extend +extern func Std_Io_PrintLine(s: String); +extern func Std_Io_PrintInt(n: int); + +struct Rectangle { + width: int; + height: int; +} + +extend Rectangle { + func Area(self: Rectangle) -> int { + return self.width * self.height; + } + + func Perimeter(self: Rectangle) -> int { + return 2 * (self.width + self.height); + } +} + +func Main() -> int { + let rect: Rectangle = Rectangle { width: 10, height: 5 }; + + Std_Io_PrintLine("Rectangle:"); + Std_Io_PrintLine("Width = "); + Std_Io_PrintInt(rect.width); + Std_Io_PrintLine(""); + Std_Io_PrintLine("Height = "); + Std_Io_PrintInt(rect.height); + Std_Io_PrintLine(""); + Std_Io_PrintLine("Area = "); + Std_Io_PrintInt(rect.Area()); + Std_Io_PrintLine(""); + Std_Io_PrintLine("Perimeter = "); + Std_Io_PrintInt(rect.Perimeter()); + Std_Io_PrintLine(""); + + return 0; +} diff --git a/src/cli.nim b/src/cli.nim index 7b7f3d8..f105a5d 100644 --- a/src/cli.nim +++ b/src/cli.nim @@ -226,7 +226,7 @@ proc cmdBuild*(args: seq[string], opts: GlobalOptions): int = for d in parseRes.diagnostics: echo &"error: {d.message} at {d.loc}" return 1 - let semaRes = analyze(parseRes.module) + let (semaRes, semaCtx) = analyzeFull(parseRes.module) if semaRes.hasErrors: printError(&"type errors in {path}", useColor) for d in semaRes.diagnostics: @@ -235,9 +235,7 @@ proc cmdBuild*(args: seq[string], opts: GlobalOptions): int = return 1 # Lower to HIR - var s = Sema(module: parseRes.module, globalScope: newScope()) - s.collectGlobals() - let hirModule = lowerModule(parseRes.module, s) + let hirModule = lowerModule(parseRes.module, semaCtx) # Generate C code var cbe = initCBackend() diff --git a/src/hir_lower.nim b/src/hir_lower.nim index 0b0a42a..9cb9cd4 100644 --- a/src/hir_lower.nim +++ b/src/hir_lower.nim @@ -148,22 +148,27 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode = of ekCall: # Method call desugaring: obj.method(args) → Type_method(obj, args) if expr.exprCallCallee.kind == ekField: - let recvType = ctx.resolveExprType(expr.exprCallCallee.exprFieldObj) let methodName = expr.exprCallCallee.exprFieldName - var typeName = "" - if recvType.kind == tkNamed: typeName = recvType.name - elif recvType.isPointer and recvType.inner.len > 0 and recvType.inner[0].kind == tkNamed: - typeName = recvType.inner[0].name - if typeName != "" and ctx.methodTable.hasKey(typeName): - for minfo in ctx.methodTable[typeName]: + + # Try to find the method in methodTable + for typeName, methods in ctx.methodTable: + for minfo in methods: if minfo.name == methodName: - # Desugar: obj.method(args) → Type_method(&obj, args) + # Found the method - desugar to Type_method(receiver, args) let mangledName = typeName & "_" & methodName var args: seq[HirNode] = @[] args.add(ctx.lowerExpr(expr.exprCallCallee.exprFieldObj)) for arg in expr.exprCallArgs: args.add(ctx.lowerExpr(arg)) return hirCall(mangledName, args, typ, loc) + + # Not a method call - treat as field access + call (function pointer) + let callee = ctx.lowerExpr(expr.exprCallCallee) + var args: seq[HirNode] = @[] + for arg in expr.exprCallArgs: + args.add(ctx.lowerExpr(arg)) + return HirNode(kind: hCallIndirect, callIndirectCallee: callee, + callIndirectArgs: args, typ: typ, loc: loc) # Regular function call var calleeName = "" diff --git a/src/sema.nim b/src/sema.nim index 600afda..008a0ae 100644 --- a/src/sema.nim +++ b/src/sema.nim @@ -573,3 +573,11 @@ proc analyze*(modu: Module): SemaResult = sema.collectGlobals() sema.checkBodies() result = SemaResult(diagnostics: sema.diagnostics) + +proc analyzeFull*(modu: Module): tuple[result: SemaResult, sema: Sema] = + ## Analyze module and return both result and full Sema context + ## Use this when you need the Sema for lowering (method table, etc.) + var sema = Sema(module: modu, globalScope: newScope()) + sema.collectGlobals() + sema.checkBodies() + result = (SemaResult(diagnostics: sema.diagnostics), sema) diff --git a/tests/hir_test b/tests/hir_test index 07470c4..23e4259 100755 Binary files a/tests/hir_test and b/tests/hir_test differ