basic for loop + examples -> era3

This commit is contained in:
Neemek 2026-07-13 10:01:13 +02:00
parent dd7af341a3
commit 0bc8b2ef55
Signed by: neemek
GPG key ID: 84FFE4D7D40AB25E
24 changed files with 222 additions and 201 deletions

View file

@ -153,6 +153,7 @@ func (c *Compiler) add(instruction Bytecode) {
c.advance(1)
}
// addConstant add both a constant (if it is not already defined), and add the index of it to the bytecode
func (c *Compiler) addConstant(value Value) {
chunk := c.Chunk
for i := 0; i < len(chunk.Constants); i++ {
@ -165,6 +166,10 @@ func (c *Compiler) addConstant(value Value) {
chunk.Constants = append(chunk.Constants, value)
if len(chunk.Constants) > 256 {
panic("too many constants (>256)")
}
c.add(Bytecode(len(chunk.Constants) - 1))
}
@ -472,7 +477,6 @@ func (c *Compiler) compile(tree Node) (TypeSignature, error) {
c.add(InstructionJumpFalse)
jumpValuePos = c.ip
c.advance(2)
}
c.add(InstructionPop)
@ -492,6 +496,74 @@ func (c *Compiler) compile(tree Node) (TypeSignature, error) {
return &CompositeSignature{dt, &NilSignature{}}, nil
case ForNodeType:
n := tree.(*ForNode)
is, err := c.compile(n.iterator)
if err != nil {
return nil, err
}
iteratorSignature := &FunctionSignature{
[]TypeSignature{},
&TupleSignature{
[]TypeSignature{
&AnySignature{},
&BooleanSignature{},
},
},
}
if !iteratorSignature.Contains(is) {
return nil, c.error(fmt.Sprintf("cannot iterate with non-iterator %s (must be %s)", is, iteratorSignature), n.iterator)
}
outputSig := is.(*FunctionSignature).Out.(*TupleSignature).Contents[0]
ipos := c.ip
c.addDescend()
c.add(InstructionDuplicate)
c.add(InstructionCall)
c.add(InstructionDestructureTuple)
// if no more items; jump to end
c.add(InstructionJumpFalse)
jmpValuePos := c.ip
c.advance(2)
if n.counter.Type() != ReferenceNodeType {
return nil, c.error("cannot use non-variable as a counter", n.counter)
}
name := n.counter.(*ReferenceNode).name
c.add(InstructionDeclareLocal)
c.addConstant(&StringValue{
name,
})
c.add(InstructionPop)
c.registerVar(name, outputSig)
_, err = c.compile(n.logic)
if err != nil {
return nil, err
}
c.add(InstructionPop)
c.addAscend()
c.add(InstructionLoop)
c.addU16(uint16(c.ip - ipos + 2))
// end of loop
c.putU16(jmpValuePos, uint16(c.ip-jmpValuePos-2))
c.add(InstructionPop)
c.add(InstructionPop)
c.add(InstructionNil)
return &NilSignature{}, nil
case AssignNodeType:
n := tree.(*AssignNode)