fspl/analyzer/function.go

60 lines
1.7 KiB
Go

package analyzer
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) analyzeFunction (
pos lexer.Position,
name string,
) (
*entity.Function,
error,
) {
var err error
// return if exists already
if function, exists := this.Functions[name]; exists {
return function, nil
}
// error if function is missing
function, exists := this.rawFunctions[name]
if !exists {
return nil, participle.Errorf(pos, "no function named %s", name)
}
// create a new scope context for this function
this.pushScopeContext(function)
this.pushScope(function)
defer this.popScopeContext()
defer this.popScope()
// analyze signature and add arguments to root scope of function
function.Signature, err = this.assembleSignatureMap(function.Signature)
if err != nil { return function, err }
for name, argument := range function.Signature.ArgumentMap {
argument.Ty, err = this.analyzeType(argument.Ty, false)
this.addVariable(argument)
function.Signature.ArgumentMap[name] = argument
if err != nil { return function, err }
}
function.Signature.Return, err =
this.analyzeType(function.Signature.Return, false)
if err != nil { return function, err }
// add incomplete function to complete functions because there is enough
// information for it to be complete from the point of view of other
// parts of the code
this.Functions[name] = function
// analyze function body
if function.Body != nil {
body, err := this.analyzeExpression (
function.Signature.Return, strict, function.Body)
if err != nil { return nil, err }
function.Body = body
}
return function, nil
}