Analyze return statement

This commit is contained in:
Sasha Koshka 2023-10-29 14:28:51 -04:00
parent 8751cc7b89
commit 359441d5fa
5 changed files with 52 additions and 6 deletions

View File

@ -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
}

View File

@ -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()

View File

@ -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()

View File

@ -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) {

View File

@ -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(){}