~madcapjake/rhi

c9a4c6368b42b95c4dc181040670de6fa2d1f497 — Jake Russo 1 year, 5 months ago 8c2bb03
Add list capture to bytecode & fix memory printer
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))