Analyze return statement
This commit is contained in:
parent
8751cc7b89
commit
359441d5fa
@ -613,3 +613,39 @@ func (this *Tree) analyzeBreak (
|
|||||||
|
|
||||||
return brk, nil
|
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
|
// create a new scope context for this function
|
||||||
this.pushScopeContext()
|
this.pushScopeContext(function)
|
||||||
this.pushScope(function)
|
this.pushScope(function)
|
||||||
defer this.popScopeContext()
|
defer this.popScopeContext()
|
||||||
defer this.popScope()
|
defer this.popScope()
|
||||||
|
@ -32,7 +32,7 @@ func (this *Tree) analyzeMethod (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a new scope context for this function
|
// create a new scope context for this function
|
||||||
this.pushScopeContext()
|
this.pushScopeContext(method)
|
||||||
this.pushScope(method)
|
this.pushScope(method)
|
||||||
defer this.popScopeContext()
|
defer this.popScopeContext()
|
||||||
defer this.popScope()
|
defer this.popScope()
|
||||||
|
@ -7,8 +7,8 @@ import "git.tebibyte.media/sashakoshka/fspl/entity"
|
|||||||
// entity causes the analysis of another.
|
// entity causes the analysis of another.
|
||||||
type scopeContextManager []scopeContext
|
type scopeContextManager []scopeContext
|
||||||
|
|
||||||
func (this *scopeContextManager) pushScopeContext () {
|
func (this *scopeContextManager) pushScopeContext (declaration entity.TopLevel) {
|
||||||
*this = append(*this, scopeContext { })
|
*this = append(*this, scopeContext { declaration: declaration })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *scopeContextManager) popScopeContext () {
|
func (this *scopeContextManager) popScopeContext () {
|
||||||
@ -31,6 +31,11 @@ func (this *scopeContextManager) topLoop () (*entity.Loop, bool) {
|
|||||||
return (*this)[len(*this) - 1].topLoop()
|
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) {
|
func (this *scopeContextManager) pushScope (scope entity.Scoped) {
|
||||||
this.assertPopulated()
|
this.assertPopulated()
|
||||||
(*this)[len(*this) - 1].pushScope(scope)
|
(*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
|
// scopeContext is a stack of scopes and loops used when analyzing scoped
|
||||||
// entities.
|
// entities.
|
||||||
type scopeContext struct {
|
type scopeContext struct {
|
||||||
scopes []entity.Scoped
|
scopes []entity.Scoped
|
||||||
loops []*entity.Loop
|
loops []*entity.Loop
|
||||||
|
declaration entity.TopLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *scopeContext) pushLoop (loop *entity.Loop) {
|
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
|
// 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.
|
// to anything. A return statement is never a valid location expression.
|
||||||
type Return struct {
|
type Return struct {
|
||||||
|
// Syntax
|
||||||
Pos lexer.Position
|
Pos lexer.Position
|
||||||
Value Expression `parser:" '[' 'return' @@? ']' "`
|
Value Expression `parser:" '[' 'return' @@? ']' "`
|
||||||
|
|
||||||
|
// Semantics
|
||||||
|
Declaration TopLevel
|
||||||
}
|
}
|
||||||
func (*Return) expression(){}
|
func (*Return) expression(){}
|
||||||
func (*Return) statement(){}
|
func (*Return) statement(){}
|
||||||
|
Loading…
Reference in New Issue
Block a user