M internal/vm/code_array.go => internal/vm/code_array.go +2 -2
@@ 24,8 24,8 @@ type CodeArray struct {
func NewCodeArray(words ...Word) CodeArray {
return CodeArray{
- Mark: Word(TAG_OBJ_ARR),
- Legend: Word(TAG_ADDRESS),
+ Mark: Word(CODE_ARR),
+ Legend: Word(VAL_ADDR),
Length: WordFromInt(uint32(len(words))),
CodeWords: words,
}
M internal/vm/map.go => internal/vm/map.go +21 -6
@@ 6,11 6,11 @@ type Map struct {
Field []Word
}
-func NewMap() Map {
+func NewMap(count uint32, legAddr Word) Map {
return Map{
- Word(TAG_OBJ_MAP),
- Word(TAG_ADDRESS), // FIXME: Empty Address
- make([]Word, 0),
+ Word(MAIN_MAP),
+ WordFromAddress(0),
+ make([]Word, count),
}
}
@@ 25,6 25,19 @@ type MapLegend struct {
Field []LegendFieldDescriptor
}
+func NewMapLegend() MapLegend {
+ return MapLegend{
+ Word(MAIN_LGD),
+ WordFromAddress(0),
+ EmptyWord(),
+ WordFromInt(0),
+ WordFromInt(0),
+ WordFromAddress(0),
+ WordFromAddress(0),
+ make([]LegendFieldDescriptor, 0),
+ }
+}
+
type RoutineLegend struct {
Mark Word
MetaLegend Word // pointer to the toplevel MapLegend
@@ 44,8 57,10 @@ type ArrayLegend struct {
Parent LegendFieldDescriptor
}
+// T
+
type LegendFieldDescriptor struct {
- Name Word
- Type Word // immutable, mutable, subfield
+ Mark Word // immutable, mutable, subfield
+ Name Word // address to TextMap
Data Word // constant, field offset, or
}
M internal/vm/primitives.go => internal/vm/primitives.go +40 -12
@@ 52,14 52,14 @@ func (vm *VirtualMachine) popStack() (popped Word) {
func (vm *VirtualMachine) gatherTwoInts() (val1, val2 uint32) {
stackVal2 := vm.popStack()
stackVal1 := vm.popStack()
- if stackVal1.IsAddr() {
+ if stackVal1.IsAddress() {
val1 = vm.heap[stackVal1.AsAddr()].AsInt()
- } else if stackVal1.IsInt() {
+ } else if stackVal1.IsInteger() {
val1 = stackVal1.AsInt()
}
- if stackVal2.IsAddr() {
+ if stackVal2.IsAddress() {
val2 = vm.heap[stackVal2.AsAddr()].AsInt()
- } else if stackVal2.IsInt() {
+ } else if stackVal2.IsInteger() {
val2 = stackVal2.AsInt()
}
return
@@ 101,29 101,57 @@ func (vm *VirtualMachine) expTwoInts() {
logAddedToStack(vm.stack, fmt.Sprint(val1, " ^ ", val2))
}
+// New scope and add a sentinel to the stack
func (vm *VirtualMachine) beginRoutine() {
vm.scope = append(vm.scope, make(map[string]int))
- vm.stack = append(vm.stack, Word(TAG_MRK_STL))
+ vm.stack = append(vm.stack, Word(SENTINEL))
}
-func (vm *VirtualMachine) endRoutine() {
- // TODO: try to delete things?
- vm.scope = vm.scope[:len(vm.scope)-1]
+// Same as routine
+func (vm *VirtualMachine) beginMap() {
+ vm.beginRoutine()
+}
+
+func (vm *VirtualMachine) unwindToSentinel() error {
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
+ vm.stack = vm.stack[:back-1]
+ return nil
}
}
+ return fmt.Errorf("No sentinel found")
}
-func (vm *VirtualMachine) beginMap() {
+// Replace all sub stack values with one final result
+func (vm *VirtualMachine) endRoutine() {
+ stackLen := len(vm.stack)
+ last := vm.stack[stackLen-1]
+ vm.scope = vm.scope[:len(vm.scope)-1]
+
+ if err := vm.unwindToSentinel(); err != nil {
+ panic(err)
+ }
+
+ vm.stack = append(vm.stack, last)
}
+// Delete all sub stack values and turn scope into map
func (vm *VirtualMachine) endMap() {
+ scopeCount := len(vm.scope)
+ // mapScope := vm.scope[scopeCount-1]
+
+ vm.scope = vm.scope[:scopeCount-1]
+
+ if err := vm.unwindToSentinel(); err != nil {
+ panic(err)
+ }
+ // mapLeg := NewMapLegend(mapScope)
+ // legAddr := vm.heap[len(vm.heap)-1]
+ // vm.heap = append(vm.heap, mapLeg.AsWords())
+ // mapObj := NewMapObject(legAddr, mapScope)
+ // vm.heap = append(vm.heap)
}
/* Phase 2
M internal/vm/rune_array.go => internal/vm/rune_array.go +1 -1
@@ 15,7 15,7 @@ type RuneArray struct {
func NewRuneArray(addr Word, words ...Word) RuneArray {
return RuneArray{
- Word(TAG_OBJ_ARR),
+ Word(RUNE_ARR),
addr,
WordFromInt(uint32(len(words))),
words,
M internal/vm/vm.go => internal/vm/vm.go +2 -2
@@ 75,14 75,14 @@ func (vm *VirtualMachine) SubmitLocalRequest(ir InstrRef) {
idx, ok := locateScopeLabel(vm.scope, ir.text)
if ok {
// TODO: Invoke address, skip addrRef
- vm.stack = append(vm.stack, WordFromAddr(idx))
+ vm.stack = append(vm.stack, WordFromAddress(idx))
logAddedToStack(vm.stack, ir.text)
return
}
vm.heap = append(vm.heap, EmptyWord())
idx = len(vm.heap) - 1
vm.scope[len(vm.scope)-1][ir.text] = idx
- vm.stack = append(vm.stack, WordFromAddr(idx))
+ vm.stack = append(vm.stack, WordFromAddress(idx))
logAddedToStack(vm.stack, ir.text)
}
M internal/vm/word.go => internal/vm/word.go +130 -65
@@ 9,36 9,68 @@ import (
type Word uint64
-const TAG_SLT_NAN uint64 = 0x7F_FC_00_00_00_00_00_00
+const MASK_NAN uint64 = 0x7F_FC_00_00_00_00_00_00
-const TAG_ADDRESS uint64 = 0x80_00_00_00_00_00_00_00
+const VAL_ADDR uint64 = 0xFF_FC_00_00_00_00_00_00
-const TAG_LIT_NAN uint64 = 0x7F_FC_00_00_00_00_00_00
-const TAG_LIT_TRU uint64 = 0x7F_FC_40_00_00_00_00_00
-const TAG_LIT_FLS uint64 = 0x7F_FC_80_00_00_00_00_00
-const TAG_LIT_ETY uint64 = 0x7F_FC_C0_00_00_00_00_00
+const MARK_ERR uint64 = 0x7F_FC_00_00_00_00_00_00
-const TAG_LIT_INT uint64 = 0x7F_FD_00_00_00_00_00_00
-const TAG_LIT_RNE uint64 = 0x7F_FD_40_00_00_00_00_00
-const TAG_LIT_SYM uint64 = 0x7F_FD_80_00_00_00_00_00
+const ERR_MAIN uint64 = 0x7F_FC_00_10_00_00_00_00
+const ERR_NUMB uint64 = 0x7F_FC_00_20_00_00_00_00
-const TAG_OBJ_MAP uint64 = 0x7F_FE_00_00_00_00_00_00
-const TAG_OBJ_ARR uint64 = 0x7F_FE_40_00_00_00_00_00
-const TAG_OBJ_ROU uint64 = 0x7F_FE_80_00_00_00_00_00
-const TAG_OBJ_CHU uint64 = 0x7F_FE_C0_00_00_00_00_00
+const VAL_TRUE uint64 = 0x7F_FC_40_00_00_00_00_00
+const VAL_FALS uint64 = 0x7F_FC_80_00_00_00_00_00
+const VAL_EMPT uint64 = 0x7F_FC_C0_00_00_00_00_00
-const TAG_LEG_MAP uint64 = 0x7F_FF_00_00_00_00_00_00
-const TAG_LEG_ARR uint64 = 0x7F_FF_10_00_00_00_00_00
-const TAG_LEG_ROU uint64 = 0x7F_FF_C0_00_00_00_00_00
+const VAL_NUMB uint64 = 0x7F_FD_00_00_00_00_00_00
+const VAL_RUNE uint64 = 0x7F_FD_40_00_00_00_00_00
+const VAL_SYMB uint64 = 0x7F_FD_80_00_00_00_00_00
+const VAL_DATE uint64 = 0x7F_FD_C0_00_00_00_00_00
-const TAG_MRK_STL uint64 = 0x7F_FD_C0_00_00_00_00_00
+const SENTINEL uint64 = 0x7F_FE_00_00_00_00_00_00
-const TAG_ALLMARK uint64 = TAG_LEG_ROU
+const MARK_MAP uint64 = 0x7F_FE_40_00_00_00_00_00
-const TAG_SWP_WHT uint64 = 0x00_00_00_00_00_00_00_00
-const TAG_SWP_GRY uint64 = 0x00_00_00_00_00_00_00_01
-const TAG_SWP_BLK uint64 = 0x00_00_00_00_00_00_00_02
-const TAG_SWPMASK uint64 = 0x00_00_00_00_00_00_00_03
+const MAIN_MAP uint64 = 0x7F_FE_40_10_00_00_00_00
+const LIST_MAP uint64 = 0x7F_FE_40_20_00_00_00_00
+const TEXT_MAP uint64 = 0x7F_FE_40_30_00_00_00_00
+const FUNC_MAP uint64 = 0x7F_FE_40_40_00_00_00_00
+const META_MAP uint64 = 0x7F_FE_40_F0_00_00_00_00
+
+const MARK_ARR uint64 = 0x7F_FE_80_00_00_00_00_00
+
+const MAIN_ARR uint64 = 0x7F_FE_80_20_00_00_00_00
+const RUNE_ARR uint64 = 0x7F_FE_80_30_00_00_00_00
+const CODE_ARR uint64 = 0x7F_FE_40_40_00_00_00_00
+const META_ARR uint64 = 0x7F_FE_80_F0_00_00_00_00
+
+const MARK_LGD uint64 = 0x7F_FE_C0_00_00_00_00_00
+
+const MAIN_LGD uint64 = 0x7F_FE_C0_10_00_00_00_00
+const LIST_LGD uint64 = 0x7F_FE_C0_20_00_00_00_00
+const TEXT_LGD uint64 = 0x7F_FE_C0_30_00_00_00_00
+const FUNC_LGD uint64 = 0x7F_FE_C0_40_00_00_00_00
+const META_LGD uint64 = 0x7F_FE_C0_F0_00_00_00_00
+
+const MARK_DES uint64 = 0x7F_FF_00_00_00_00_00_00
+
+const DES_NUMB uint64 = 0x7F_FF_00_10_00_00_00_00
+const DES_FLOA uint64 = 0x7F_FF_00_20_00_00_00_00
+const DES_BOOL uint64 = 0x7F_FF_00_30_00_00_00_00
+const DES_RUNE uint64 = 0x7F_FF_00_40_00_00_00_00
+const DES_SYMB uint64 = 0x7F_FF_00_50_00_00_00_00
+const DES_DATE uint64 = 0x7F_FF_00_60_00_00_00_00
+const DES_ADDR uint64 = 0x7F_FF_00_70_00_00_00_00
+
+const CMP_UNIT uint64 = 0x7F_FF_40_00_00_00_00_00
+
+const TAG_IMMU uint64 = 0x00_00_08_00_00_00_00_00
+const TAG_MUTA uint64 = 0x00_00_0C_00_00_00_00_00
+const TAG_GREY uint64 = 0x00_00_02_00_00_00_00_00
+const TAG_BLAK uint64 = 0x00_00_03_00_00_00_00_00
+
+const MASK_ONE uint64 = 0x7F_FF_C0_00_00_00_00_00
+const MASK_TWO uint64 = 0x7F_FF_C0_F0_00_00_00_00
func NewWord(a any) Word {
switch a := a.(type) {
@@ 59,7 91,8 @@ func NewWord(a any) Word {
}
}
-func EmptyWord() Word { return Word(TAG_LIT_ETY) }
+func EmptyWord() Word { return Word(VAL_EMPT) }
+func NotANumberWord() Word { return Word(ERR_NUMB) }
func WordFromFloat(f float64) Word {
var bytes [8]byte
@@ 77,34 110,66 @@ func WordFromFloat(f float64) Word {
func WordFromBool(b bool) Word {
if b {
- return Word(TAG_LIT_TRU)
+ return Word(VAL_TRUE)
} else {
- return Word(TAG_LIT_FLS)
+ return Word(VAL_FALS)
}
}
-func WordFromInt(i uint32) Word { return Word(TAG_LIT_INT | uint64(i)) }
-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) 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) }
-func (w Word) IsArray() bool { return w.isMrkT(TAG_OBJ_ARR) }
-func (w Word) IsRoutine() bool { return w.isMrkT(TAG_OBJ_ROU) }
-func (w Word) IsChunk() bool { return w.isMrkT(TAG_OBJ_CHU) }
+func WordFromInt(i uint32) Word { return Word(VAL_NUMB | uint64(i)) }
+func WordFromRune(r rune) Word { return Word(VAL_RUNE | uint64(r)) }
+func WordFromSym(a int) Word { return Word(VAL_SYMB | uint64(a)) }
+func WordFromAddress(a int) Word { return Word(VAL_ADDR | uint64(a)) }
+
+func (w Word) isVal(v uint64) bool { return uint64(w)&MASK_ONE == v }
+
+func (w Word) IsFloat() bool { return uint64(w)&MASK_NAN != MASK_NAN }
+func (w Word) IsAddress() bool { return w.isVal(VAL_ADDR) }
+func (w Word) IsTrue() bool { return uint64(w) == VAL_TRUE }
+func (w Word) IsFalse() bool { return uint64(w) == VAL_FALS }
+func (w Word) IsBool() bool { return w.IsTrue() || w.IsFalse() }
+func (w Word) IsEmpty() bool { return uint64(w) == VAL_EMPT }
+func (w Word) IsInteger() bool { return w.isVal(VAL_NUMB) }
+func (w Word) IsRune() bool { return w.isVal(VAL_RUNE) }
+func (w Word) IsDate() bool { return w.isVal(VAL_DATE) }
+func (w Word) IsSym() bool { return w.isVal(VAL_SYMB) }
+
+func (w Word) IsSentinel() bool { return uint64(w) == SENTINEL }
+
+func (w Word) isMark(m uint64) bool { return uint64(w)&MASK_ONE == m }
+
+func (w Word) IsNAN() bool { return w.isMark(ERR_NUMB) }
+
+func (w Word) IsAnyMark() bool { return uint64(w)&MASK_ONE > MARK_MAP }
+func (w Word) IsMapMark() bool { return w.isMark(MARK_MAP) }
+func (w Word) IsMainMapMark() bool { return w.isMark(MAIN_MAP) }
+func (w Word) IsListMapMark() bool { return w.isMark(LIST_MAP) }
+func (w Word) IsTextMapMark() bool { return w.isMark(TEXT_MAP) }
+func (w Word) IsFuncMapMark() bool { return w.isMark(FUNC_MAP) }
+func (w Word) IsMetaMapMark() bool { return w.isMark(META_MAP) }
+
+func (w Word) IsArrayMark() bool { return w.isMark(MARK_ARR) }
+func (w Word) IsMainArrayMark() bool { return w.isMark(MAIN_ARR) }
+func (w Word) IsRuneArrayMark() bool { return w.isMark(RUNE_ARR) }
+func (w Word) IsCodeArrayMark() bool { return w.isMark(CODE_ARR) }
+func (w Word) IsMetaArrayMark() bool { return w.isMark(META_ARR) }
+
+func (w Word) IsLegendMark() bool { return w.isMark(MARK_LGD) }
+func (w Word) IsMainLegendMark() bool { return w.isMark(MAIN_LGD) }
+func (w Word) IsListLegendMark() bool { return w.isMark(LIST_LGD) }
+func (w Word) IsTextLegendMark() bool { return w.isMark(TEXT_LGD) }
+func (w Word) IsFuncLegendMark() bool { return w.isMark(FUNC_LGD) }
+func (w Word) IsMetaLegendMark() bool { return w.isMark(META_LGD) }
+
+func (w Word) IsDescMark() bool { return w.isMark(MARK_DES) }
+func (w Word) IsIntegerDescMark() bool { return w.isMark(DES_NUMB) }
+func (w Word) IsFloatDescMark() bool { return w.isMark(DES_FLOA) }
+func (w Word) IsBoolDescMark() bool { return w.isMark(DES_BOOL) }
+func (w Word) IsRuneDescMark() bool { return w.isMark(DES_RUNE) }
+func (w Word) IsSymbolDescMark() bool { return w.isMark(DES_SYMB) }
+func (w Word) IsDateDescMark() bool { return w.isMark(DES_DATE) }
+func (w Word) IsAddressDescMark() bool { return w.isMark(DES_ADDR) }
+
+func (w Word) IsChunk() bool { return w.isMark(CMP_UNIT) }
func (w Word) Debug() any {
if w.IsNAN() {
@@ 115,21 180,21 @@ func (w Word) Debug() any {
return "FALSE"
} else if w.IsEmpty() {
return "EMPTY"
- } else if w.IsInt() {
+ } else if w.IsInteger() {
return fmt.Sprint("{INT: ", w.AsInt(), "}")
} else if w.IsRune() {
return fmt.Sprint("{RUNE: ", w.AsRune(), "}")
} else if w.IsSym() {
return "SYMBOL" // FIXME: Implement symbols
- } else if w.IsAddr() { // must trigger before IsFloat for unknown reasons
+ } else if w.IsAddress() { // must trigger before IsFloat for unknown reasons
return fmt.Sprint("{ADDR: ", w.AsAddr(), "}")
} else if w.IsFloat() {
return fmt.Sprint("{FLOAT: ", w.AsFloat(), "}")
- } else if w.IsMap() {
+ } else if w.IsMapMark() {
return "MAP"
- } else if w.IsArray() {
+ } else if w.IsArrayMark() {
return "ARRAY"
- } else if w.IsRoutine() {
+ } else if w.IsFuncMapMark() {
return "ROUTINE"
} else if w.IsChunk() {
return "CHUNK"
@@ 138,20 203,20 @@ func (w Word) Debug() any {
}
}
-func (w Word) isSwpT(t uint64) bool {
- return uint64(w)&(TAG_OBJ_MAP|TAG_SWPMASK) == t
-}
-func (w Word) IsGrey() bool { return w.isSwpT(TAG_OBJ_MAP | TAG_SWP_GRY) }
-func (w Word) IsBlack() bool { return w.isSwpT(TAG_OBJ_MAP | TAG_SWP_BLK) }
+// func (w Word) isSwpT(t uint64) bool {
+// return uint64(w)&(TAG_OBJ_MAP|TAG_SWPMASK) == t
+// }
+// func (w Word) IsGrey() bool { return w.isSwpT(TAG_OBJ_MAP | TAG_SWP_GRY) }
+// func (w Word) IsBlack() bool { return w.isSwpT(TAG_OBJ_MAP | TAG_SWP_BLK) }
func (w Word) AsBool() bool {
switch uint64(w) {
- case TAG_LIT_TRU:
+ case VAL_TRUE:
return true
- case TAG_LIT_FLS, TAG_LIT_ETY, TAG_LIT_NAN:
+ case VAL_FALS, VAL_EMPT, ERR_NUMB:
return false
default:
- return w.IsAddr()
+ return w.IsAddress()
}
}
@@ 164,7 229,7 @@ func (w Word) AsFloat() float64 {
float := math.Float64frombits(bits)
return float
}
-func (w Word) AsInt() uint32 { return uint32(uint64(w) & ^TAG_LIT_INT) }
-func (w Word) AsRune() rune { return rune(uint64(w) & ^TAG_LIT_RNE) }
-func (w Word) AsSym() uint64 { return uint64(w) & ^TAG_LIT_SYM }
-func (w Word) AsAddr() uint64 { return uint64(w) & ^TAG_ADDRESS }
+func (w Word) AsInt() uint32 { return uint32(uint64(w) & ^VAL_NUMB) }
+func (w Word) AsRune() rune { return rune(uint64(w) & ^VAL_RUNE) }
+func (w Word) AsSym() uint64 { return uint64(w) & ^VAL_SYMB }
+func (w Word) AsAddr() uint64 { return uint64(w) & ^VAL_ADDR }
M internal/vm/word_array.go => internal/vm/word_array.go +2 -2
@@ 11,8 11,8 @@ type WordArray struct {
func NewWordArray(words ...Word) WordArray {
return WordArray{
- Word(TAG_OBJ_ARR),
- Word(TAG_ADDRESS),
+ Word(MAIN_ARR),
+ Word(VAL_ADDR),
WordFromInt(uint32(len(words))),
words,
}