fspl/analyzer/function.go

67 lines
1.8 KiB
Go

package analyzer
import "git.tebibyte.media/fspl/fspl/errors"
import "git.tebibyte.media/fspl/fspl/entity"
func (this *Tree) analyzeFunction (
pos errors.Position,
key entity.Key,
) (
*entity.Function,
error,
) {
var err error
// return if exists already
if function, exists := this.Functions[key]; exists {
return function, nil
}
// error if function is missing
function, exists := this.rawFunctions[key]
if !exists {
return nil, errors.Errorf(pos, "no function named %s", key.Name)
}
// set unit
function.Unt = key.Unit
// functions cannot be marked as opaque
if function.Acc == entity.AccessOpaque {
return nil, errors.Errorf(pos, "cannot mark function as opaque")
}
// 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[key] = 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
}