Add expression functions with context boundaries

This commit is contained in:
pavel 2026-08-27 23:05:49 +02:00
commit 773c34f3f4
18 changed files with 391 additions and 52 deletions

View file

@ -109,9 +109,11 @@ type HIRMapping struct {
func (HIRMapping) hirNode() {}
type HIRFunction struct {
Symbol *Symbol
Decl *FunctionDecl
Scope *Scope
Symbol *Symbol
Decl *FunctionDecl
Scope *Scope
Expression *HIRExpr
Result Type
}
type HIRProgram struct {
@ -249,8 +251,19 @@ func (resolver *semanticResolver) resolve() error {
_ = scope.Define(&Symbol{Name: param.Name, Kind: VariableSymbol, Type: typ})
}
result, _ := resolver.program.ResolveTypeRefWithParams(decl.ReturnRef, decl.TypeParams)
resolver.resolveStmts(decl.Body, scope, nil, result)
resolver.program.HIR.Functions = append(resolver.program.HIR.Functions, &HIRFunction{Symbol: symbol, Decl: decl, Scope: scope})
var expression *HIRExpr
if decl.ExpressionBody != nil {
expected := result
if decl.InferReturn {
expected = UnknownType{}
}
decl.ExpressionBody, result = resolver.resolveExpr(decl.ExpressionBody, scope, nil, expected)
expression = exprMeta(decl.ExpressionBody)
resolver.updateFunctionResult(symbol, result)
} else {
resolver.resolveStmts(decl.Body, scope, nil, result)
}
resolver.program.HIR.Functions = append(resolver.program.HIR.Functions, &HIRFunction{Symbol: symbol, Decl: decl, Scope: scope, Expression: expression, Result: result})
}
for classIndex := range resolver.program.Syntax.Classes {
decl := &resolver.program.Syntax.Classes[classIndex]
@ -266,13 +279,69 @@ func (resolver *semanticResolver) resolve() error {
}
params := append(append([]string{}, decl.TypeParams...), method.TypeParams...)
result, _ := resolver.program.ResolveTypeRefWithParams(method.ReturnRef, params)
resolver.resolveStmts(method.Body, scope, class, result)
resolver.program.HIR.Methods = append(resolver.program.HIR.Methods, &HIRFunction{Symbol: class.Methods[method.Name], Decl: method, Scope: scope})
var expression *HIRExpr
if method.ExpressionBody != nil {
expected := result
if method.InferReturn {
expected = UnknownType{}
}
method.ExpressionBody, result = resolver.resolveExpr(method.ExpressionBody, scope, class, expected)
expression = exprMeta(method.ExpressionBody)
resolver.updateFunctionResult(class.Methods[method.Name], result)
} else {
resolver.resolveStmts(method.Body, scope, class, result)
}
resolver.program.HIR.Methods = append(resolver.program.HIR.Methods, &HIRFunction{Symbol: class.Methods[method.Name], Decl: method, Scope: scope, Expression: expression, Result: result})
}
}
resolver.inferExpressionReturns()
return resolver.err
}
func (resolver *semanticResolver) inferExpressionReturns() {
changed := true
for changed {
changed = false
for _, function := range append(append([]*HIRFunction{}, resolver.program.HIR.Functions...), resolver.program.HIR.Methods...) {
if function.Decl == nil || !function.Decl.InferReturn || function.Decl.ExpressionBody == nil {
continue
}
var class *ClassSymbol
if function.Symbol != nil {
for _, candidate := range resolver.program.ClassInfo {
if candidate.Method(function.Symbol.Name) == function.Symbol {
class = candidate
break
}
}
}
result := resolver.program.TypeOf(function.Decl.ExpressionBody, TypeEnvironment{Scope: function.Scope, Class: class})
if isUnknownType(result) {
continue
}
current := function.Result
if isUnknownType(current) || !typeEqual(current, result) {
function.Result = result
if function.Expression != nil {
function.Expression.Type = result
}
resolver.updateFunctionResult(function.Symbol, result)
changed = true
}
}
}
}
func (resolver *semanticResolver) updateFunctionResult(symbol *Symbol, result Type) {
if symbol == nil {
return
}
if function, ok := symbol.Type.(FunctionType); ok {
function.Result = result
symbol.Type = function
}
}
func (resolver *semanticResolver) resolveStmts(stmts []Stmt, scope *Scope, class *ClassSymbol, returnType Type) {
for index, stmt := range stmts {
switch value := stmt.(type) {
@ -768,7 +837,7 @@ var semanticBuiltins = map[string]bool{
"make": true, "new": true, "copy": true, "delete": true, "close": true,
"panic": true, "recover": true, "string": true, "int": true, "float64": true, "bool": true,
"sql": true, "set": true, "now": true, "Result": true, "ByteSlice": true,
"runBlocking": true, "coroutineScope": true, "launch": true, "async": true,
"runBlocking": true, "withContext": true, "coroutineScope": true, "launch": true, "async": true,
"delay": true, "withTimeout": true, "isActive": true, "coroutineContext": true,
"continue": true, "break": true,
}