summaryrefslogtreecommitdiff
path: root/parser/parse.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2026-01-23 11:16:12 +0100
committerMarc Vertes <mvertes@free.fr>2026-01-23 11:16:12 +0100
commit2837dabf7818666a9366d659d2da3b9055140740 (patch)
tree3d4fce18fe750044b519e571845d4b476f958656 /parser/parse.go
parentabd8581bac36018be2f090e05fdd00ea74f6ca4b (diff)
feat: make Next iterator instruction faster and more efficient
Branching control is delegated directly to the Next instruction, which now takes the location of loop exit as first argument. It avoids the use of JumpFalse, plus the stack storage for the condition.
Diffstat (limited to 'parser/parse.go')
-rw-r--r--parser/parse.go17
1 files changed, 10 insertions, 7 deletions
diff --git a/parser/parse.go b/parser/parse.go
index daf30ca..e72e16e 100644
--- a/parser/parse.go
+++ b/parser/parse.go
@@ -201,6 +201,7 @@ func (p *Parser) parseGoto(in Tokens) (out Tokens, err error) {
func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
// TODO: detect invalid code.
var init, cond, post, body, final Tokens
+ hasRange := in.Index(lang.Range) >= 0
fc := strconv.Itoa(p.labelCount[p.scope])
p.labelCount[p.scope]++
breakLabel, continueLabel := p.breakLabel, p.continueLabel
@@ -213,10 +214,10 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
pre := in[1 : len(in)-1].Split(lang.Semicolon)
switch len(pre) {
case 1:
- if in.Index(lang.Range) >= 0 {
+ if hasRange {
init = pre[0]
- cond = Tokens{{Token: scanner.Token{Tok: lang.Next}}}
- final = Tokens{{Token: scanner.Token{Tok: lang.Stop}}}
+ cond = Tokens{newNext(p.breakLabel, in[1].Pos)}
+ final = Tokens{newStop(in[1].Pos)}
} else {
cond = pre[0]
}
@@ -231,13 +232,15 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
}
out = init
}
- out = append(out, newLabel(p.scope+"b", in[0].Pos))
+ out = append(out, newLabel(p.continueLabel, in[0].Pos))
if len(cond) > 0 {
if cond, err = p.parseExpr(cond, ""); err != nil {
return nil, err
}
out = append(out, cond...)
- out = append(out, newJumpFalse(p.scope+"e", in[0].Pos))
+ if !hasRange {
+ out = append(out, newJumpFalse(p.breakLabel, in[0].Pos))
+ }
}
if body, err = p.Parse(in[len(in)-1].Block()); err != nil {
return nil, err
@@ -250,8 +253,8 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
out = append(out, post...)
}
out = append(out,
- newGoto(p.scope+"b", in[0].Pos),
- newLabel(p.scope+"e", in[0].Pos),
+ newGoto(p.continueLabel, in[0].Pos),
+ newLabel(p.breakLabel, in[0].Pos),
)
out = append(out, final...)
return out, err