Analyze return statement
This commit is contained in:
parent
8751cc7b89
commit
359441d5fa
@ -613,3 +613,39 @@ func (this *Tree) analyzeBreak (
|
||||
|
||||
return brk, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeReturn (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
ret *entity.Return,
|
||||
) (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
if into != nil {
|
||||
return nil, participle.Errorf(ret.Pos, "expected %v", into)
|
||||
}
|
||||
|
||||
ret.Declaration, _ = this.topDeclaration()
|
||||
var ty entity.Type
|
||||
switch ret.Declaration.(type) {
|
||||
case *entity.Function:
|
||||
ty = ret.Declaration.(*entity.Function).Signature.Return
|
||||
case *entity.Method:
|
||||
ty = ret.Declaration.(*entity.Method).Signature.Return
|
||||
}
|
||||
|
||||
if !ty.Equals(&entity.TypeVoid { }) && ret.Value == nil {
|
||||
return nil, participle.Errorf (
|
||||
ret.Pos,
|
||||
"break statement must have value")
|
||||
}
|
||||
|
||||
if ret.Value != nil {
|
||||
value, err := this.analyzeExpression(ty, strict, ret.Value)
|
||||
if err != nil { return nil, err }
|
||||
ret.Value = value
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ func (this *Tree) analyzeFunction (
|
||||
}
|
||||
|
||||
// create a new scope context for this function
|
||||
this.pushScopeContext()
|
||||
this.pushScopeContext(function)
|
||||
this.pushScope(function)
|
||||
defer this.popScopeContext()
|
||||
defer this.popScope()
|
||||
|
@ -32,7 +32,7 @@ func (this *Tree) analyzeMethod (
|
||||
}
|
||||
|
||||
// create a new scope context for this function
|
||||
this.pushScopeContext()
|
||||
this.pushScopeContext(method)
|
||||
this.pushScope(method)
|
||||
defer this.popScopeContext()
|
||||
defer this.popScope()
|
||||
|
@ -7,8 +7,8 @@ import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||
// entity causes the analysis of another.
|
||||
type scopeContextManager []scopeContext
|
||||
|
||||
func (this *scopeContextManager) pushScopeContext () {
|
||||
*this = append(*this, scopeContext { })
|
||||
func (this *scopeContextManager) pushScopeContext (declaration entity.TopLevel) {
|
||||
*this = append(*this, scopeContext { declaration: declaration })
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) popScopeContext () {
|
||||
@ -31,6 +31,11 @@ func (this *scopeContextManager) topLoop () (*entity.Loop, bool) {
|
||||
return (*this)[len(*this) - 1].topLoop()
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) topDeclaration () (entity.TopLevel, bool) {
|
||||
if len(*this) < 1 { return nil, false }
|
||||
return (*this)[len(*this) - 1].declaration, true
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) pushScope (scope entity.Scoped) {
|
||||
this.assertPopulated()
|
||||
(*this)[len(*this) - 1].pushScope(scope)
|
||||
@ -67,8 +72,9 @@ func (this *scopeContextManager) assertPopulated () {
|
||||
// scopeContext is a stack of scopes and loops used when analyzing scoped
|
||||
// entities.
|
||||
type scopeContext struct {
|
||||
scopes []entity.Scoped
|
||||
loops []*entity.Loop
|
||||
scopes []entity.Scoped
|
||||
loops []*entity.Loop
|
||||
declaration entity.TopLevel
|
||||
}
|
||||
|
||||
func (this *scopeContext) pushLoop (loop *entity.Loop) {
|
||||
|
@ -379,8 +379,12 @@ func (this *Break) String () string {
|
||||
// value. In all cases, return statements have no value and may not be assigned
|
||||
// to anything. A return statement is never a valid location expression.
|
||||
type Return struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Value Expression `parser:" '[' 'return' @@? ']' "`
|
||||
|
||||
// Semantics
|
||||
Declaration TopLevel
|
||||
}
|
||||
func (*Return) expression(){}
|
||||
func (*Return) statement(){}
|
||||
|
Loading…
Reference in New Issue
Block a user