feat: add method call support and analyzeFull
- Add analyzeFull() to return Sema context with method table - Improve method call desugaring: obj.method() → Type_method(obj) - Search methodTable by method name when type inference fails - Add methods.bux example demonstrating struct with extend blocks - Use analyzeFull in cli.nim for proper method resolution
This commit is contained in:
@@ -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;
|
||||
}
|
||||
+2
-4
@@ -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()
|
||||
|
||||
+13
-8
@@ -148,16 +148,13 @@ 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))
|
||||
@@ -165,6 +162,14 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
|
||||
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 = ""
|
||||
if expr.exprCallCallee.kind == ekIdent:
|
||||
|
||||
@@ -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)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user