Skip to content

Commit

Permalink
Add 'while' loop statement to ZSS
Browse files Browse the repository at this point in the history
Syntax example:

let i = 0;
map(domino) := 0;

while  < 2 {
	let i =  + 1;
	while map(domino) < (5 * ) {
		map(domino) := map(domino) + 1;
	}
}

While accepts any conditional expression, meaning, it can create infinite loops. In that case, Ikemen GO will freeze.
  • Loading branch information
Lazin3ss committed Jan 16, 2023
1 parent d5334ea commit ac826fd
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
49 changes: 36 additions & 13 deletions src/bytecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -2075,13 +2075,16 @@ func (cf callFunction) Run(c *Char, _ []int32) (changeState bool) {
}

type StateBlock struct {
// Basic block fields
persistent int32
persistentIndex int32
ignorehitpause int32
ctrlsIgnorehitpause bool
trigger BytecodeExp
elseBlock *StateBlock
ctrls []StateController
// Loop fields
loopBlock bool
}

func newStateBlock() *StateBlock {
Expand All @@ -2107,22 +2110,42 @@ func (b StateBlock) Run(c *Char, ps []int32) (changeState bool) {
}
}
sys.workingChar = c
if len(b.trigger) > 0 && !b.trigger.evalB(c) {
if b.elseBlock != nil {
return b.elseBlock.Run(c, ps)
if b.loopBlock {
for {
if len(b.trigger) > 0 && !b.trigger.evalB(c) {
break
}
for _, sc := range b.ctrls {
switch sc.(type) {
case StateBlock:
default:
if !b.ctrlsIgnorehitpause && c.hitPause() {
continue
}
}
if sc.Run(c, ps) {
return true
}
}
}
return false
}
for _, sc := range b.ctrls {
switch sc.(type) {
case StateBlock:
default:
if !b.ctrlsIgnorehitpause && c.hitPause() {
continue
} else {
if len(b.trigger) > 0 && !b.trigger.evalB(c) {
if b.elseBlock != nil {
return b.elseBlock.Run(c, ps)
}
return false
}
if sc.Run(c, ps) {
return true
for _, sc := range b.ctrls {
switch sc.(type) {
case StateBlock:
default:
if !b.ctrlsIgnorehitpause && c.hitPause() {
continue
}
}
if sc.Run(c, ps) {
return true
}
}
}
if b.persistentIndex >= 0 {
Expand Down
27 changes: 26 additions & 1 deletion src/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4522,6 +4522,10 @@ func (c *Compiler) subBlock(line *string, root bool,
if err := c.switchBlock(line, bl, sbc, numVars); err != nil {
return nil, err
}
case "while":
if err := c.loopBlock(line, bl, sbc, numVars); err != nil {
return nil, err
}
default:
return nil, c.yokisinaiToken()
}
Expand Down Expand Up @@ -4663,6 +4667,27 @@ func (c *Compiler) switchBlock(line *string, bl *StateBlock,
}
return nil
}
func (c *Compiler) loopBlock(line *string, bl *StateBlock,
sbc *StateBytecode, numVars *int32) error {
bl.loopBlock = true
switch c.token {
// case "for": // TODO: make for loop
case "while":
expr, _, err := c.readSentence(line)
if err != nil {
return err
}
otk := c.token
if bl.trigger, err = c.fullExpression(&expr, VT_Bool); err != nil {
return err
}
c.token = otk
if err := c.needToken("{"); err != nil {
return err
}
}
return nil
}
func (c *Compiler) callFunc(line *string, root bool,
ctrls *[]StateController, ret []uint8) error {
var cf callFunction
Expand Down Expand Up @@ -4757,7 +4782,7 @@ func (c *Compiler) stateBlock(line *string, bl *StateBlock, root bool,
return c.yokisinaiToken()
}
return nil
case "if", "ignorehitpause", "persistent", "switch":
case "if", "ignorehitpause", "persistent", "switch", "while":
if sbl, err := c.subBlock(line, root, sbc, numVars,
bl != nil && bl.ctrlsIgnorehitpause); err != nil {
return err
Expand Down

0 comments on commit ac826fd

Please sign in to comment.