~madcapjake/rhi

c63f3e9ac28ce670b7dbc0fdbc58a127be84cae8 — Jake Russo 1 year, 9 months ago f6ef4d2
Expand more primitives
4 files changed, 85 insertions(+), 39 deletions(-)

M .vscode/launch.json
M internal/vm/primitives.go
M internal/vm/vm.go
M internal/vm/word.go
M .vscode/launch.json => .vscode/launch.json +1 -1
@@ 19,7 19,7 @@
            "program": "cmd/rhumb/main.go",
            "args": [
                "line",
                "foo := 1; bar .= 1"
                "foo .= 10; bar .= 3; foo ** bar // 6"
            ]
        }


M internal/vm/primitives.go => internal/vm/primitives.go +63 -27
@@ 24,6 24,24 @@ func locateScopeLabel(
	return
}

func expBySquaring(x, n uint32) uint32 {
	if n == 0 {
		return 1
	}
	var y uint32 = 1
	for n > 1 {
		if n%2 == 0 {
			x = x * x
			n = n / 2
		} else {
			y = x * y
			x = x * x
			n = (n - 1) / 2
		}
	}
	return x * y
}

func (vm *VirtualMachine) popStack() (popped Word) {
	idx := len(vm.stack) - 1
	popped = vm.stack[idx]


@@ 31,6 49,22 @@ func (vm *VirtualMachine) popStack() (popped Word) {
	return
}

func (vm *VirtualMachine) gatherTwoInts() (val1, val2 uint32) {
	stackVal2 := vm.popStack()
	stackVal1 := vm.popStack()
	if stackVal1.IsAddr() {
		val1 = vm.heap[stackVal1.AsAddr()].AsInt()
	} else if stackVal1.IsInt() {
		val1 = stackVal1.AsInt()
	}
	if stackVal2.IsAddr() {
		val2 = vm.heap[stackVal2.AsAddr()].AsInt()
	} else if stackVal2.IsInt() {
		val2 = stackVal2.AsInt()
	}
	return
}

func (vm *VirtualMachine) assignLabel() {
	valWord := vm.popStack()
	addrWord := vm.popStack()


@@ 38,56 72,58 @@ func (vm *VirtualMachine) assignLabel() {
}

func (vm *VirtualMachine) addTwoInts() {
	val2 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1, val2 := vm.gatherTwoInts()
	vm.stack = append(vm.stack, WordFromInt(val1+val2))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " + ", val2))
}

func (vm *VirtualMachine) subTwoInts() {
	val2 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1, val2 := vm.gatherTwoInts()
	vm.stack = append(vm.stack, WordFromInt(val1-val2))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " - ", val2))
}

func (vm *VirtualMachine) mulTwoInts() {
	val2 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1, val2 := vm.gatherTwoInts()
	vm.stack = append(vm.stack, WordFromInt(val1*val2))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " x ", val2))
}

func (vm *VirtualMachine) divTwoInts() {
	val2 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1, val2 := vm.gatherTwoInts()
	vm.stack = append(vm.stack, WordFromInt(val1/val2))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " / ", val2))
}

func expBySquaring(x, n uint32) uint32 {
	if n == 0 {
		return 1
	}
	var y uint32 = 1
	for n > 1 {
		if n%2 == 0 {
			x = x * x
			n = n / 2
		} else {
			y = x * y
			x = x * x
			n = (n - 1) / 2
func (vm *VirtualMachine) expTwoInts() {
	val1, val2 := vm.gatherTwoInts()
	vm.stack = append(vm.stack, WordFromInt(expBySquaring(val1, val2)))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " ^ ", val2))
}

func (vm *VirtualMachine) beginRoutine() {
	vm.scope = append(vm.scope, make(map[string]int))
	vm.stack = append(vm.stack, Word(TAG_MRK_STL))
}

func (vm *VirtualMachine) endRoutine() {
	// TODO: try to delete things?
	vm.scope = vm.scope[:len(vm.scope)-1]
	for back := len(vm.stack); back > 0; back-- {
		if vm.stack[back].IsSentinel() {
			last := vm.stack[len(vm.stack)-1]
			vm.stack = vm.stack[:back]
			vm.stack[back] = last
		}
	}
	return x * y
}

func (vm *VirtualMachine) expTwoInts() {
	val2 := vm.heap[vm.popStack().AsAddr()].AsInt()
	val1 := vm.heap[vm.popStack().AsAddr()].AsInt()
	vm.stack = append(vm.stack, WordFromInt(expBySquaring(val1, val2)))
	logAddedToStack(vm.stack, fmt.Sprint(val1, " ^ ", val2))
func (vm *VirtualMachine) beginMap() {

}

func (vm *VirtualMachine) endMap() {

}

/* Phase 2

M internal/vm/vm.go => internal/vm/vm.go +9 -0
@@ 97,6 97,15 @@ func (vm *VirtualMachine) SubmitOuterRequest(ir InstrRef) {
		vm.divTwoInts()
	case "^^":
		vm.expTwoInts()
	case "[[":
		vm.beginMap()
	case "]]":
		vm.endMap()
	case "((":
		vm.beginRoutine()
	case "))":
		vm.endRoutine()

	default:
		panic("Not a valid outer operator")
	}

M internal/vm/word.go => internal/vm/word.go +12 -11
@@ 87,17 87,18 @@ func WordFromRune(r rune) Word  { return Word(TAG_LIT_RNE | uint64(r)) }
func WordFromSym(a int) Word    { return Word(TAG_LIT_SYM | uint64(a)) }
func WordFromAddr(a int) Word   { return Word(TAG_ADDRESS | uint64(a)) }

func (w Word) IsNAN() bool   { return uint64(w) == TAG_LIT_NAN }
func (w Word) IsTrue() bool  { return uint64(w) == TAG_LIT_TRU }
func (w Word) IsFalse() bool { return uint64(w) == TAG_LIT_FLS }
func (w Word) IsBool() bool  { return w.IsTrue() || w.IsFalse() }
func (w Word) IsEmpty() bool { return uint64(w) == TAG_LIT_ETY }
func (w Word) IsInt() bool   { return uint64(w)&TAG_LIT_INT == TAG_LIT_INT }
func (w Word) IsRune() bool  { return uint64(w)&TAG_LIT_RNE == TAG_LIT_RNE }
func (w Word) IsSym() bool   { return uint64(w)&TAG_LIT_SYM == TAG_LIT_SYM }
func (w Word) IsFloat() bool { return uint64(w)&TAG_SLT_NAN != TAG_SLT_NAN }
func (w Word) IsMark() bool  { return uint64(w)&TAG_OBJ_MAP == TAG_OBJ_MAP }
func (w Word) IsAddr() bool  { return uint64(w)&TAG_ADDRESS == TAG_ADDRESS }
func (w Word) IsFloat() bool    { return uint64(w)&TAG_SLT_NAN != TAG_SLT_NAN }
func (w Word) IsAddr() bool     { return uint64(w)&TAG_ADDRESS == TAG_ADDRESS }
func (w Word) IsNAN() bool      { return uint64(w) == TAG_LIT_NAN }
func (w Word) IsTrue() bool     { return uint64(w) == TAG_LIT_TRU }
func (w Word) IsFalse() bool    { return uint64(w) == TAG_LIT_FLS }
func (w Word) IsBool() bool     { return w.IsTrue() || w.IsFalse() }
func (w Word) IsEmpty() bool    { return uint64(w) == TAG_LIT_ETY }
func (w Word) IsInt() bool      { return uint64(w)&TAG_LIT_INT == TAG_LIT_INT }
func (w Word) IsRune() bool     { return uint64(w)&TAG_LIT_RNE == TAG_LIT_RNE }
func (w Word) IsSym() bool      { return uint64(w)&TAG_LIT_SYM == TAG_LIT_SYM }
func (w Word) IsSentinel() bool { return uint64(w)&TAG_MRK_STL == TAG_MRK_STL }
func (w Word) IsMark() bool     { return uint64(w)&TAG_OBJ_MAP == TAG_OBJ_MAP }

func (w Word) isMrkT(t uint64) bool { return uint64(w)&TAG_ALLMARK == t }
func (w Word) IsMap() bool          { return w.isMrkT(TAG_OBJ_MAP) }