M internal/generator/visitor.go => internal/generator/visitor.go +4 -1
@@ 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()
M internal/vm/array-word.go => internal/vm/array-word.go +5 -6
@@ 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) (
M internal/vm/chunk.go => internal/vm/chunk.go +1 -1
@@ 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) {
M internal/vm/legend-list.go => internal/vm/legend-list.go +2 -0
@@ 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 {
M internal/vm/legend.go => internal/vm/legend.go +22 -5
@@ 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")
+ }
+}
M internal/vm/map-list.go => internal/vm/map-list.go +4 -4
@@ 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 {
M internal/vm/map.go => internal/vm/map.go +6 -13
@@ 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 {
M internal/vm/primitives.go => internal/vm/primitives.go +21 -5
@@ 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))
M internal/vm/vm.go => internal/vm/vm.go +7 -5
@@ 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))