From c922c797204069f42a7abf88500c5708f68a8e43 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Wed, 21 Jan 2026 19:26:42 +0100 Subject: feat: add support for range clause and iterators - vm: added Pull, Next and Stop instructions, to implement iterators - lang: add Range, Next and Stop tokens - parser: handle range clause. Still naive and incomplete. - comp: generate iterator instructions from range clause. Work in progress. Only initial support for slices. Many more tests and combinations needed, but the main pattern is there now. --- vm/op_string.go | 23 +++++++++++++---------- vm/vm.go | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'vm') diff --git a/vm/op_string.go b/vm/op_string.go index f53ce5e..594bc3b 100644 --- a/vm/op_string.go +++ b/vm/op_string.go @@ -44,19 +44,22 @@ func _() { _ = x[Mul-33] _ = x[New-34] _ = x[Negate-35] - _ = x[Not-36] - _ = x[Pop-37] - _ = x[Push-38] - _ = x[Return-39] - _ = x[Slice-40] - _ = x[Slice3-41] - _ = x[Sub-42] - _ = x[Swap-43] + _ = x[Next-36] + _ = x[Not-37] + _ = x[Pop-38] + _ = x[Push-39] + _ = x[Pull-40] + _ = x[Return-41] + _ = x[Slice-42] + _ = x[Slice3-43] + _ = x[Stop-44] + _ = x[Sub-45] + _ = x[Swap-46] } -const _Op_name = "NopAddAddrAssignFassignVassignCallCallXDerefDupFdupFnewFnewEEqualEqualSetExitFieldFieldEFieldSetFieldFsetGreaterGrowIndexIndexSetJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLenLowerMapIndexMapSetMulNewNegateNotPopPushReturnSliceSlice3SubSwap" +const _Op_name = "NopAddAddrAssignFassignVassignCallCallXDerefDupFdupFnewFnewEEqualEqualSetExitFieldFieldEFieldSetFieldFsetGreaterGrowIndexIndexSetJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLenLowerMapIndexMapSetMulNewNegateNextNotPopPushPullReturnSliceSlice3StopSubSwap" -var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 47, 51, 55, 60, 65, 73, 77, 82, 88, 96, 105, 112, 116, 121, 129, 133, 141, 150, 161, 173, 176, 181, 189, 195, 198, 201, 207, 210, 213, 217, 223, 228, 234, 237, 241} +var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 47, 51, 55, 60, 65, 73, 77, 82, 88, 96, 105, 112, 116, 121, 129, 133, 141, 150, 161, 173, 176, 181, 189, 195, 198, 201, 207, 211, 214, 217, 221, 225, 231, 236, 242, 246, 249, 253} func (i Op) String() string { idx := int(i) - 0 diff --git a/vm/vm.go b/vm/vm.go index 07ea8e0..f6dc6fc 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -2,7 +2,8 @@ package vm import ( - "fmt" // for tracing only + "fmt" // for tracing only + "iter" "log" // for tracing only "reflect" // for optional CallX only "strings" @@ -55,12 +56,15 @@ const ( Mul // n1 n2 -- prod ; prod = n1*n2 New // -- x; mem[fp+$1] = new mem[$2] Negate // -- ; - mem[fp] + Next // -- ; iterator next Not // c -- r ; r = !c Pop // v -- Push // -- v + Pull // a -- a s n; pull iterator next and stop function Return // [r1 .. ri] -- ; exit frame: sp = fp, fp = pop Slice // a l h -- a; a = a [l:h] Slice3 // a l h m -- a; a = a[l:h:m] + Stop // -- iterator stop Sub // n1 n2 -- diff ; diff = n1 - n2 Swap // -- ) @@ -242,6 +246,12 @@ func (m *Machine) Run() (err error) { mem = append(mem, ValueOf(mem[sp-1-c.Arg[0]].Len())) case Negate: mem[sp-1] = ValueOf(-mem[sp-1].Int()) + case Next: + v, ok := mem[sp-2].Interface().(func() (reflect.Value, bool))() + if ok { + mem[c.Arg[0]].Set(v) + } + mem = append(mem, ValueOf(ok)) case Not: mem[sp-1] = ValueOf(!mem[sp-1].Bool()) case Pop: @@ -249,6 +259,9 @@ func (m *Machine) Run() (err error) { case Push: mem = append(mem, NewValue(TypeOf(0))) mem[sp].SetInt(int64(c.Arg[0])) + case Pull: + next, stop := iter.Pull(mem[sp-1].Seq()) + mem = append(mem, ValueOf(next), ValueOf(stop)) case Grow: mem = append(mem, make([]Value, c.Arg[0])...) case Return: @@ -263,6 +276,9 @@ func (m *Machine) Run() (err error) { case Slice3: mem[sp-4].Value = mem[sp-4].Slice3(int(mem[sp-3].Int()), int(mem[sp-2].Int()), int(mem[sp-1].Int())) mem = mem[:sp-3] + case Stop: + mem[sp-1].Interface().(func())() + mem = mem[:sp-4] case Sub: mem[sp-2] = ValueOf(int(mem[sp-2].Int() - mem[sp-1].Int())) mem = mem[:sp-1] -- cgit v1.2.3