From c9a4c6368b42b95c4dc181040670de6fa2d1f497 Mon Sep 17 00:00:00 2001 From: Jake Russo Date: Mon, 10 Apr 2023 21:42:00 -0500 Subject: [PATCH] Add list capture to bytecode & fix memory printer --- internal/generator/visitor.go | 5 ++++- internal/vm/array-word.go | 11 +++++------ internal/vm/chunk.go | 2 +- internal/vm/legend-list.go | 2 ++ internal/vm/legend.go | 27 ++++++++++++++++++++++----- internal/vm/map-list.go | 8 ++++---- internal/vm/map.go | 19 ++++++------------- internal/vm/primitives.go | 26 +++++++++++++++++++++----- internal/vm/vm.go | 12 +++++++----- 9 files changed, 72 insertions(+), 40 deletions(-) diff --git a/internal/generator/visitor.go b/internal/generator/visitor.go index c72d598..617cba5 100644 --- a/internal/generator/visitor.go +++ b/internal/generator/visitor.go @@ -371,7 +371,10 @@ func (v *RhumbVisitor) VisitMap(ctx *P.MapContext) interface{} { vm.NewOuterRequest, // FIXME: re-implement as NewInnerRequest ) - v.VisitChildren(ctx.Sequence()) + for i, n := range ctx.Sequence().GetChildren() { + viLogger.Printf("map{%d} -> %s\n", i, reflect.TypeOf(n)) + v.Visit(n.(antlr.ParseTree)) + } bracket = ctx.CloseBracket().GetSymbol() text = bracket.GetText() diff --git a/internal/vm/array-word.go b/internal/vm/array-word.go index 65e7978..7a50898 100644 --- a/internal/vm/array-word.go +++ b/internal/vm/array-word.go @@ -39,22 +39,21 @@ func NewWordArray( return WordArray{uint64(loc)} } -func ReviveWordArray(vm *VirtualMachine, addr word.Word) WordArray { - i := addr.AsAddr() - mark := vm.Heap[i] +func ReviveWordArray(vm *VirtualMachine, addr uint64) WordArray { + mark := vm.Heap[addr] if !(mark.IsListArrayMark()) { panic("not a word array mark") } - legend := vm.Heap[i+word_lgd_offset] + legend := vm.Heap[addr+word_lgd_offset] if !(legend.IsAddress()) { // fmt.Println(legend.Debug()) panic("word array legend word is not an address") } - length := vm.Heap[i+word_len_offset] + length := vm.Heap[addr+word_len_offset] if !(length.IsInteger()) { panic("word array object length word is not an integer") } - return WordArray{i} + return WordArray{addr} } func (wa WordArray) Find(vm *VirtualMachine, s string) ( diff --git a/internal/vm/chunk.go b/internal/vm/chunk.go index 5ddbcd1..af3c726 100644 --- a/internal/vm/chunk.go +++ b/internal/vm/chunk.go @@ -97,7 +97,7 @@ func (ch RhumbChunk) Literals(vm *VirtualMachine) word.Word { } func (ch RhumbChunk) ReviveLits(vm *VirtualMachine) WordArray { - return ReviveWordArray(vm, ch.Literals(vm)) + return ReviveWordArray(vm, ch.Literals(vm).AsAddr()) } func (ch RhumbChunk) Execute(vm *VirtualMachine) { diff --git a/internal/vm/legend-list.go b/internal/vm/legend-list.go index e0567aa..dbed39a 100644 --- a/internal/vm/legend-list.go +++ b/internal/vm/legend-list.go @@ -7,6 +7,7 @@ import ( func NewListLegend(virtualMachine *VirtualMachine) Legend { words := make([]word.Word, 0, 8) init_size := uint32(lgd_fld_offset) + dataArray := NewWordArray(virtualMachine, word.FromAddress(0)) words = append(words, /* Mark: */ word.Word(word.LIST_LGD), /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend @@ -15,6 +16,7 @@ func NewListLegend(virtualMachine *VirtualMachine) Legend { /* Length: */ word.FromInt(0), /* ReqLink: */ word.FromAddress(0), /* DepLink: */ word.FromAddress(0), + /* Data: */ word.FromAddress(dataArray.id), ) loc, err := virtualMachine.ReAllocate(words...) if err != nil { diff --git a/internal/vm/legend.go b/internal/vm/legend.go index 2cbef39..f8a6668 100644 --- a/internal/vm/legend.go +++ b/internal/vm/legend.go @@ -10,11 +10,11 @@ const ( lgd_lgd_offset uint64 = 1 lgd_swp_offset uint64 = 2 lgd_sze_offset uint64 = 3 - lgd_len_offset uint64 = 3 - lgd_req_offset uint64 = 4 - lgd_dep_offset uint64 = 5 - lgd_dat_offset uint64 = 6 - lgd_fld_offset uint64 = 7 + lgd_len_offset uint64 = 4 + lgd_req_offset uint64 = 5 + lgd_dep_offset uint64 = 6 + lgd_dat_offset uint64 = 7 + lgd_fld_offset uint64 = 8 ) type Legend struct{ Id uint64 } @@ -107,3 +107,20 @@ func (l Legend) Size(vm *VirtualMachine) uint32 { func (l Legend) SetSize(vm *VirtualMachine, i uint32) { vm.Heap[l.Id+lgd_sze_offset] = word.FromInt(i) } + +func (l Legend) Data(vm *VirtualMachine) uint64 { + return vm.Heap[l.Id+lgd_dat_offset].AsAddr() +} + +func (l Legend) Append(vm *VirtualMachine, newWords ...word.Word) { + mark := vm.Heap[l.Id] + if mark.IsListLegendMark() { + data := ReviveWordArray(vm, l.Data(vm)) + data.Append(vm, newWords...) + // } else if mark.IsTextLegendMark() { + // data := ReviveRuneArray(vm, l.Data(vm)) + // data.Append(vm, newWords...) + } else { + panic("no other append type implemented at this time") + } +} diff --git a/internal/vm/map-list.go b/internal/vm/map-list.go index 9d53292..b0ce445 100644 --- a/internal/vm/map-list.go +++ b/internal/vm/map-list.go @@ -9,13 +9,13 @@ func NewListMap(virtualMachine *VirtualMachine) Map { words := make([]word.Word, 0, map_fld_offset) words = append(words, /* Mark: */ word.Word(word.LIST_MAP), - /* Legend: */ word.Word(legend.Id), + /* Legend: */ word.FromAddress(legend.Id), ) - loc, err := virtualMachine.ReAllocate(words...) - if err != nil { + if loc, err := virtualMachine.ReAllocate(words...); err != nil { panic("allocation failed") + } else { + return Map{Id: loc} } - return Map{Id: loc} } func ReviveListMap(virtualMachine *VirtualMachine, addr word.Word) Map { diff --git a/internal/vm/map.go b/internal/vm/map.go index b875ee6..c2e72fa 100644 --- a/internal/vm/map.go +++ b/internal/vm/map.go @@ -24,20 +24,13 @@ func CheckMapWords( } } -func (m Map) Append(vm *VirtualMachine, newWord word.Word) Map { - oldLen := m.Length(vm) - oldSze := m.Size(vm) - id, err := vm.Allocate(int(m.Id), int(m.Size(vm)), newWord) - if err != nil { - panic("word array append failed") - } else { - if id != m.Id { - m.Id = id - } - m.SetLength(vm, oldLen+1) - m.SetSize(vm, oldSze+1) - return m +func (m Map) Append(vm *VirtualMachine, newWords ...word.Word) Map { + legend := m.ReviveLegend(vm) + legend.Append(vm, newWords...) + if legend.Id != m.Legend(vm) { + m.SetLegend(vm, legend.Id) } + return m } func (m Map) Get(vm *VirtualMachine, name RuneArray) word.Word { diff --git a/internal/vm/primitives.go b/internal/vm/primitives.go index b374322..6a473de 100644 --- a/internal/vm/primitives.go +++ b/internal/vm/primitives.go @@ -111,11 +111,16 @@ func (vm *VirtualMachine) beginMap() { logAddedToStack(vm.Stack, "*Map") } -func (vm *VirtualMachine) unwindToSentinel() error { +func (vm *VirtualMachine) unwindToSentinel(each ...func(w word.Word)) error { for back := len(vm.Stack) - 1; back > 0; back-- { - if vm.Stack[back].IsSentinel() { + currentWord := vm.Stack[back] + if currentWord.IsSentinel() { vm.Stack = vm.Stack[:back] return nil + } else { + for _, fn := range each { + fn(currentWord) + } } } return fmt.Errorf("no sentinel found") @@ -138,17 +143,28 @@ func (vm *VirtualMachine) endRoutine() { // Delete all sub stack values and place map address on stack func (vm *VirtualMachine) endMap() { - last := len(vm.MapScope) - 1 - currMap := vm.MapScope[last] + var ( + last int = len(vm.MapScope) - 1 + currMap Map = vm.MapScope[last] + unwoundVals []word.Word = make([]word.Word, 0) + storePositionalVal func(word.Word) = func(w word.Word) { + unwoundVals = append(unwoundVals, w) + } + ) + if last == 0 { vm.MapScope = nil } else { vm.MapScope = vm.MapScope[:last-1] } - if err := vm.unwindToSentinel(); err != nil { + if err := vm.unwindToSentinel(storePositionalVal); err != nil { panic(err) } + for i, j := 0, len(unwoundVals)-1; i < j; i, j = i+1, j-1 { + unwoundVals[i], unwoundVals[j] = unwoundVals[j], unwoundVals[i] + } + currMap.Append(vm, unwoundVals...) vm.Stack = append(vm.Stack, word.FromAddress(currMap.Id)) logAddedToStack(vm.Stack, fmt.Sprint("Map@", currMap.Id)) diff --git a/internal/vm/vm.go b/internal/vm/vm.go index 887adee..cdd5c78 100644 --- a/internal/vm/vm.go +++ b/internal/vm/vm.go @@ -59,11 +59,13 @@ func (vm VirtualMachine) DebugHeap() { fmt.Printf("[%3v: ", j) ra := ReviveRuneArray(&vm, uint64(i)) runes := ra.Runes(&vm) - if len(runes) <= 2 { - for _, r := range runes { - fmt.Printf("'%s'", string(r)) - fmt.Print(" ") - } + if len(runes) == 1 { + fmt.Printf("'%s' ", + string(runes[0])) + } else if len(runes) == 2 { + fmt.Printf("'%s' '%s' ", + string(runes[0]), + string(runes[1])) } else { for i, r := range runes { fmt.Printf("'%s'", string(r)) -- 2.45.2