Add expression functions with context boundaries
This commit is contained in:
parent
5085ae51aa
commit
773c34f3f4
18 changed files with 391 additions and 52 deletions
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue