M .vscode/launch.json => .vscode/launch.json +9 -9
@@ 24,14 24,14 @@
// "foo := 1; bar .= 2; foo ++ bar",
-
- "foo .= 10",
- "bar .= 3",
- "foo ++ 5"
+ "foo .= [1;2;3]"
+ // "foo .= 10",
+ // "bar .= 3",
+ // "foo ++ 5"
],
"env": {
- "RHUMB_VISITOR_DEBUG": "0",
- "RHUMB_CODE_ARRAY_DEBUG": "0",
+ "RHUMB_VISITOR_DEBUG": "1",
+ "RHUMB_CODE_ARRAY_DEBUG": "1",
"RHUMB_VM_DEBUG": "1"
}
},
@@ 46,9 46,9 @@
"repl"
],
"env": {
- "RHUMB_VISITOR_DEBUG": "1",
- "RHUMB_CODE_ARRAY_DEBUG": "1",
- "RHUMB_VM_DEBUG": "1"
+ "RHUMB_VISITOR_DEBUG": "0",
+ "RHUMB_CODE_ARRAY_DEBUG": "0",
+ "RHUMB_VM_DEBUG": "0"
}
}
M internal/generator/visitor.go => internal/generator/visitor.go +42 -1
@@ 347,7 347,48 @@ func (v *RhumbVisitor) VisitPower(ctx *P.PowerContext) interface{} {
func (v *RhumbVisitor) VisitMap(ctx *P.MapContext) interface{} {
viLogger.Println("map:", ctx.GetText())
- return v.VisitChildren(ctx)
+ var (
+ ra vm.RuneArray
+ oBrcktIdx, cBrcktIdx uint64
+ oBrcktFindErr, cBrcktFindErr error
+ lits vm.WordArray = v.vm.CurrentChunk.ReviveLits(&v.vm)
+ bracket antlr.Token
+ line int
+ text string
+ )
+ bracket = ctx.OpenBracket().GetSymbol()
+ text = bracket.GetText()
+ line = bracket.GetLine()
+ oBrcktIdx, oBrcktFindErr = lits.Find(&v.vm, text)
+ if oBrcktFindErr != nil {
+ ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), []rune(text)...)
+ oBrcktIdx = ra.Id()
+ }
+
+ v.vm.WriteCodeToCurrentChunk(
+ line,
+ word.FromAddress(oBrcktIdx),
+ vm.NewOuterRequest, // FIXME: re-implement as NewInnerRequest
+ )
+
+ v.VisitChildren(ctx.Sequence())
+
+ bracket = ctx.CloseBracket().GetSymbol()
+ text = bracket.GetText()
+ line = bracket.GetLine()
+ cBrcktIdx, cBrcktFindErr = lits.Find(&v.vm, text)
+ if cBrcktFindErr != nil {
+ ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), []rune(text)...)
+ cBrcktIdx = ra.Id()
+ }
+
+ v.vm.WriteCodeToCurrentChunk(
+ line,
+ word.FromAddress(cBrcktIdx),
+ vm.NewOuterRequest, // FIXME: re-implement as NewInnerRequest
+ )
+
+ return nil
}
func (v *RhumbVisitor) VisitFreeze(ctx *P.FreezeContext) interface{} {
R internal/vm/code_array.go => internal/vm/array-code.go +15 -35
@@ 57,20 57,20 @@ func NewCodeArray(
if err != nil {
panic("allocation failed")
}
- return CodeArray{uint64(loc)}
+ return CodeArray{loc}
}
func ReviveCodeArray(vm *VirtualMachine, addr word.Word) CodeArray {
i := addr.AsAddr()
- mark := vm.heap[i]
+ mark := vm.Heap[i]
if !(mark.IsCodeArrayMark()) {
panic("not a code array mark")
}
- legend := vm.heap[i+code_lgd_offset]
+ legend := vm.Heap[i+code_lgd_offset]
if !(legend.IsAddress()) {
panic("code array legend word is not an address")
}
- size := vm.heap[i+code_sze_offset]
+ size := vm.Heap[i+code_sze_offset]
if !(size.IsInteger()) {
panic("code array object size word is not an integer")
}
@@ 99,7 99,7 @@ func (ca CodeArray) NewSize(vm *VirtualMachine, newLine bool, cs ...Code) (size
} else {
size = origSize
id := ca.id + code_arr_offset + uint64(ca.Size(vm)-1)
- word := vm.heap[id]
+ word := vm.Heap[id]
remainder = ca.getWordCodeCount(vm, word)
freshLength = newLength - remainder
wholeWords = freshLength / 8
@@ 132,9 132,9 @@ func (ca *CodeArray) SetCodes(
if newLine {
ws = append(ws, word.Sentinel())
} else {
- ca.getCodesFromWord(vm, vm.heap[lastWordID], &bs)
+ ca.getCodesFromWord(vm, vm.Heap[lastWordID], &bs)
if len(bs) < 8 {
- vm.free[lastWordID] = true
+ vm.Free[lastWordID] = true
origSz--
tempCS := make([]Code, len(cs))
copy(tempCS, cs)
@@ 176,30 176,10 @@ func (ca *CodeArray) SetCodes(
ws...,
)
if newId != ca.id {
- // vm.UpdateAddresses(ca.id, newId)
ca.id = newId
}
}
-func (ca *CodeArray) lastWordVacancy(vm *VirtualMachine) bool {
- var (
- lastIndex uint64 = uint64(ca.Size(vm) - 1)
- word word.Word = vm.heap[ca.id+lastIndex]
- )
- if word.IsSentinel() {
- return false
- }
- return ca.getWordCodeCount(vm, word) != 0
-}
-
-// func (ca *CodeArray) currentIndex(vm *VirtualMachine) int {
-// if ca.lastWordVacancy(vm) {
-// return int(ca.Length(vm)) - 1
-// } else {
-// return int(ca.Length(vm))
-// }
-// }
-
func (ca CodeArray) getCodesFromWord(vm *VirtualMachine, word word.Word, b *[]byte) {
var buf []byte = *b
if word.IsSentinel() {
@@ 237,7 217,7 @@ func (ca CodeArray) GetCodes(vm *VirtualMachine) []byte {
buf []byte = make([]byte, 0, cwLen*8)
)
for wIndex := code_arr_offset; wIndex < cwLen; wIndex++ {
- w := vm.heap[ca.id+wIndex]
+ w := vm.Heap[ca.id+wIndex]
if !(w.IsSentinel()) {
ca.getCodesFromWord(vm, w, &buf)
}
@@ 251,12 231,12 @@ func (ca *CodeArray) GetLine(vm *VirtualMachine, codeIndex int) (lines int) {
panic("index greater than length")
}
for i := uint64(0); i < cwSize && codes <= codeIndex; i++ {
- if vm.heap[ca.id+code_arr_offset+i].IsSentinel() {
+ if vm.Heap[ca.id+code_arr_offset+i].IsSentinel() {
lines += 1
} else {
var (
id uint64 = ca.id + code_arr_offset + i
- word word.Word = vm.heap[id]
+ word word.Word = vm.Heap[id]
)
codes += ca.getWordCodeCount(vm, word)
}
@@ 265,19 245,19 @@ func (ca *CodeArray) GetLine(vm *VirtualMachine, codeIndex int) (lines int) {
}
func (ca CodeArray) Legend(vm *VirtualMachine) uint64 {
- return vm.heap[ca.id+code_lgd_offset].AsAddr()
+ return vm.Heap[ca.id+code_lgd_offset].AsAddr()
}
func (ca CodeArray) Size(vm *VirtualMachine) uint64 {
- return uint64(vm.heap[ca.id+code_sze_offset].AsInt())
+ return uint64(vm.Heap[ca.id+code_sze_offset].AsInt())
}
func (ca CodeArray) Length(vm *VirtualMachine) uint32 {
- return vm.heap[ca.id+code_len_offset].AsInt()
+ return vm.Heap[ca.id+code_len_offset].AsInt()
}
func (ca *CodeArray) SetSize(vm *VirtualMachine, s uint32) {
- vm.heap[ca.id+code_sze_offset] = word.FromInt(s)
+ vm.Heap[ca.id+code_sze_offset] = word.FromInt(s)
}
func (ca *CodeArray) SetLength(vm *VirtualMachine, l uint32) {
- vm.heap[ca.id+code_len_offset] = word.FromInt(l)
+ vm.Heap[ca.id+code_len_offset] = word.FromInt(l)
}
R internal/vm/rune_array.go => internal/vm/array-rune.go +13 -25
@@ 7,14 7,6 @@ import (
"git.sr.ht/~madcapjake/grhumb/internal/word"
)
-// type RuneArray struct {
-// Mark word.Word
-// Legend word.Word // Address
-// Size word.Word
-// Length word.Word
-// Runes []word.Word // Words are packed 2-elem runes
-// }
-
const (
rune_lgd_offset uint64 = 1
rune_sze_offset uint64 = 2
@@ 85,20 77,16 @@ func NewRuneArray(
return RuneArray{uint64(loc)}
}
-// func GetOrMakeLabelRA(vm *VirtualMachine, text string) RuneArray {
-
-// }
-
func ReviveRuneArray(vm *VirtualMachine, addr uint64) RuneArray {
- mark := vm.heap[addr]
+ mark := vm.Heap[addr]
if !(mark.IsRuneArrayMark()) {
panic("not a rune array mark")
}
- legend := vm.heap[addr+rune_lgd_offset]
+ legend := vm.Heap[addr+rune_lgd_offset]
if !(legend.IsAddress()) {
panic("rune array legend word is not an address")
}
- size := vm.heap[addr+rune_sze_offset]
+ size := vm.Heap[addr+rune_sze_offset]
if !(size.IsInteger()) {
panic("rune array object size word is not an integer")
}
@@ 108,21 96,21 @@ func ReviveRuneArray(vm *VirtualMachine, addr uint64) RuneArray {
func (ra RuneArray) Id() uint64 { return ra.id }
func (ra RuneArray) Legend(vm *VirtualMachine) uint64 {
- return vm.heap[ra.id+rune_lgd_offset].AsAddr()
+ return vm.Heap[ra.id+rune_lgd_offset].AsAddr()
}
func (ra RuneArray) Size(vm *VirtualMachine) uint64 {
- return uint64(vm.heap[ra.id+rune_sze_offset].AsInt())
+ return uint64(vm.Heap[ra.id+rune_sze_offset].AsInt())
}
func (ra RuneArray) Length(vm *VirtualMachine) uint32 {
- return vm.heap[ra.id+rune_len_offset].AsInt()
+ return vm.Heap[ra.id+rune_len_offset].AsInt()
}
func (ra RuneArray) Runes(vm *VirtualMachine) []rune {
raLen := uint64(ra.Length(vm))
buf := make([]rune, 0, raLen)
start := ra.id + rune_arr_offset
- for i := range vm.heap[start : ra.id+ra.Size(vm)] {
+ for i := range vm.Heap[start : ra.id+ra.Size(vm)] {
bytes := make([]byte, 8)
- binary.BigEndian.PutUint64(bytes, uint64(vm.heap[start+uint64(i)]))
+ binary.BigEndian.PutUint64(bytes, uint64(vm.Heap[start+uint64(i)]))
buf = append(buf, rune(binary.LittleEndian.Uint32(bytes[:4])))
secondRune := rune(binary.LittleEndian.Uint32(bytes[4:]))
if secondRune != 0 {
@@ 140,7 128,7 @@ func (ra RuneArray) Rune(vm *VirtualMachine, i uint32) rune {
addr := i / 2
offset := i % 2
bytes := make([]byte, 8)
- binary.LittleEndian.PutUint64(bytes, uint64(vm.heap[ra.id+uint64(addr)]))
+ binary.LittleEndian.PutUint64(bytes, uint64(vm.Heap[ra.id+uint64(addr)]))
if offset == 0 {
return rune(binary.LittleEndian.Uint32(bytes[:4]))
} else {
@@ 149,11 137,11 @@ func (ra RuneArray) Rune(vm *VirtualMachine, i uint32) rune {
}
func (ra RuneArray) SetSize(vm *VirtualMachine, s uint32) {
- vm.heap[ra.id+rune_sze_offset] = word.FromInt(s)
+ vm.Heap[ra.id+rune_sze_offset] = word.FromInt(s)
}
func (ra RuneArray) SetLength(vm *VirtualMachine, l uint32) {
- vm.heap[ra.id+rune_len_offset] = word.FromInt(l)
+ vm.Heap[ra.id+rune_len_offset] = word.FromInt(l)
}
func (ra RuneArray) SetRune(vm *VirtualMachine, i uint32, r rune) {
@@ 165,7 153,7 @@ func (ra RuneArray) SetRune(vm *VirtualMachine, i uint32, r rune) {
wordBytes []byte = make([]byte, 8)
)
binary.LittleEndian.PutUint32(runeBytes, uint32(r))
- binary.LittleEndian.PutUint64(wordBytes, uint64(vm.heap[id]))
+ binary.LittleEndian.PutUint64(wordBytes, uint64(vm.Heap[id]))
if offset == 0 {
copy(wordBytes, runeBytes)
} else {
@@ 173,5 161,5 @@ func (ra RuneArray) SetRune(vm *VirtualMachine, i uint32, r rune) {
wordBytes[i+4] = rb
}
}
- vm.heap[id] = word.Word(binary.LittleEndian.Uint64(wordBytes))
+ vm.Heap[id] = word.Word(binary.LittleEndian.Uint64(wordBytes))
}
R internal/vm/word_array.go => internal/vm/array-word.go +15 -22
@@ 6,13 6,6 @@ import (
"git.sr.ht/~madcapjake/grhumb/internal/word"
)
-// type WordArray struct {
-// Mark word.Word
-// Legend word.Word // Address
-// Length word.Word // Integer
-// Words []word.Word
-// }
-
const (
word_lgd_offset uint64 = 1
word_len_offset uint64 = 2
@@ 33,7 26,7 @@ func NewWordArray(
wordsSize := uint32(code_arr_offset) + wordsLen
waWords := make([]word.Word, 0, wordsSize)
waWords = append(waWords,
- /* Mark: */ word.Word(word.MAIN_ARR),
+ /* Mark: */ word.Word(word.LIST_ARR),
/* Legend: */ legAddr,
/* Length: */ word.FromInt(wordsLen),
)
@@ 48,16 41,16 @@ func NewWordArray(
func ReviveWordArray(vm *VirtualMachine, addr word.Word) WordArray {
i := addr.AsAddr()
- mark := vm.heap[i]
- if !(mark.IsMainArrayMark()) {
+ mark := vm.Heap[i]
+ if !(mark.IsListArrayMark()) {
panic("not a word array mark")
}
- legend := vm.heap[i+word_lgd_offset]
+ legend := vm.Heap[i+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[i+word_len_offset]
if !(length.IsInteger()) {
panic("word array object length word is not an integer")
}
@@ 71,13 64,13 @@ func (wa WordArray) Find(vm *VirtualMachine, s string) (
for i := range make([]int, wa.Length(vm)) {
waVal := wa.Get(vm, i)
if waVal.IsAddress() {
- heapVal := vm.heap[waVal.AsAddr()]
+ heapVal := vm.Heap[waVal.AsAddr()]
if heapVal.IsRuneArrayMark() {
heapRA := ReviveRuneArray(vm, waVal.AsAddr())
strVal := heapRA.String(vm)
if strVal == s {
heapIdx := wa.id + word_arr_offset + uint64(i)
- idx = vm.heap[heapIdx].AsAddr()
+ idx = vm.Heap[heapIdx].AsAddr()
return
}
}
@@ 92,16 85,16 @@ func (wa WordArray) IndexOf(vm *VirtualMachine, x word.Word) (
err error,
) {
if x.IsAddress() {
- mkX := vm.heap[x.AsAddr()]
+ mkX := vm.Heap[x.AsAddr()]
if mkX.IsRuneArrayMark() {
raX := ReviveRuneArray(vm, x.AsAddr())
for i := range make([]int, wa.Length(vm)) {
y := wa.Get(vm, i)
if y.IsAddress() {
- mkY := vm.heap[y.AsAddr()]
+ mkY := vm.Heap[y.AsAddr()]
if mkY.IsRuneArrayMark() {
- ray := ReviveRuneArray(vm, y.AsAddr())
- if raX.String(vm) == ray.String(vm) {
+ raY := ReviveRuneArray(vm, y.AsAddr())
+ if raX.String(vm) == raY.String(vm) {
return i, nil
}
}
@@ 139,19 132,19 @@ func (wa WordArray) Get(vm *VirtualMachine, i int) word.Word {
if i < 0 || i >= waLen {
panic("index out of bounds")
}
- return vm.heap[wa.id+word_arr_offset+uint64(i)]
+ return vm.Heap[wa.id+word_arr_offset+uint64(i)]
}
func (wa WordArray) Legend(vm *VirtualMachine, i int) word.Word {
- return vm.heap[i]
+ return vm.Heap[i]
}
func (wa WordArray) SetLength(vm *VirtualMachine, l uint32) {
- vm.heap[wa.id+word_len_offset] = word.FromInt(l)
+ vm.Heap[wa.id+word_len_offset] = word.FromInt(l)
}
func (wa WordArray) Length(vm *VirtualMachine) int {
- return int(vm.heap[wa.id+word_len_offset].AsInt())
+ return int(vm.Heap[wa.id+word_len_offset].AsInt())
}
func (wa WordArray) Size(vm *VirtualMachine) int {
M internal/vm/chunk.go => internal/vm/chunk.go +42 -30
@@ 11,7 11,7 @@ const (
chunk_wa_offset uint64 = 2
)
-type Chunk struct {
+type RhumbChunk struct {
// address in vm's heap
id uint64
@@ 19,7 19,7 @@ type Chunk struct {
line int
}
-func NewChunk(vm *VirtualMachine) Chunk {
+func NewChunk(vm *VirtualMachine) RhumbChunk {
var (
ch [3]word.Word = [3]word.Word{}
ca CodeArray = NewCodeArray(vm, word.FromAddress(0))
@@ 32,19 32,19 @@ func NewChunk(vm *VirtualMachine) Chunk {
if err != nil {
panic("failed to reallocate onto heap")
}
- return Chunk{id, 0}
+ return RhumbChunk{id, 0}
}
-func ReviveChunk(vm *VirtualMachine, addr word.Word) Chunk {
+func ReviveChunk(vm *VirtualMachine, addr word.Word) RhumbChunk {
i := addr.AsAddr()
- mark := vm.heap[i]
+ mark := vm.Heap[i]
if !(mark.IsCodeArrayMark()) {
panic("not a chunk mark")
}
- return Chunk{i, 0}
+ return RhumbChunk{i, 0}
}
-func (ch *Chunk) WriteCode(vm *VirtualMachine, line int, codes []Code) {
+func (ch *RhumbChunk) WriteCode(vm *VirtualMachine, line int, codes []Code) {
instructions := ch.ReviveInstrs(vm)
if line > ch.line {
@@ 58,15 58,15 @@ func (ch *Chunk) WriteCode(vm *VirtualMachine, line int, codes []Code) {
}
}
-func (ch Chunk) SetInstructionsAddress(vm *VirtualMachine, addr uint64) {
- vm.heap[ch.id+chunk_ca_offset] = word.FromAddress(addr)
+func (ch RhumbChunk) SetInstructionsAddress(vm *VirtualMachine, addr uint64) {
+ vm.Heap[ch.id+chunk_ca_offset] = word.FromAddress(addr)
}
-func (ch Chunk) SetLiteralsAddress(vm *VirtualMachine, addr uint64) {
- vm.heap[ch.id+chunk_wa_offset] = word.FromAddress(addr)
+func (ch RhumbChunk) SetLiteralsAddress(vm *VirtualMachine, addr uint64) {
+ vm.Heap[ch.id+chunk_wa_offset] = word.FromAddress(addr)
}
-func (ch *Chunk) AddLiteral(vm *VirtualMachine, lit word.Word) (uint64, error) {
+func (ch *RhumbChunk) AddLiteral(vm *VirtualMachine, lit word.Word) (uint64, error) {
literals := ch.ReviveLits(vm)
existingIndex, err := literals.IndexOf(vm, lit)
if err != nil {
@@ 84,23 84,23 @@ func (ch *Chunk) AddLiteral(vm *VirtualMachine, lit word.Word) (uint64, error) {
}
}
-func (ch Chunk) Instructions(vm *VirtualMachine) word.Word {
- return vm.heap[ch.id+chunk_ca_offset]
+func (ch RhumbChunk) Instructions(vm *VirtualMachine) word.Word {
+ return vm.Heap[ch.id+chunk_ca_offset]
}
-func (ch Chunk) ReviveInstrs(vm *VirtualMachine) CodeArray {
+func (ch RhumbChunk) ReviveInstrs(vm *VirtualMachine) CodeArray {
return ReviveCodeArray(vm, ch.Instructions(vm))
}
-func (ch Chunk) Literals(vm *VirtualMachine) word.Word {
- return vm.heap[ch.id+chunk_wa_offset]
+func (ch RhumbChunk) Literals(vm *VirtualMachine) word.Word {
+ return vm.Heap[ch.id+chunk_wa_offset]
}
-func (ch Chunk) ReviveLits(vm *VirtualMachine) WordArray {
+func (ch RhumbChunk) ReviveLits(vm *VirtualMachine) WordArray {
return ReviveWordArray(vm, ch.Literals(vm))
}
-func (ch Chunk) Execute(vm *VirtualMachine) {
+func (ch RhumbChunk) Execute(vm *VirtualMachine) {
var (
instructions = ch.ReviveInstrs(vm)
cwLen int = int(instructions.Size(vm) - code_arr_offset)
@@ 108,7 108,7 @@ func (ch Chunk) Execute(vm *VirtualMachine) {
buf []byte = make([]byte, 0, cwLen*8)
)
for wordIndex := 0; wordIndex < cwLen; wordIndex++ {
- w := vm.heap[instructions.id+code_arr_offset+uint64(wordIndex)]
+ w := vm.Heap[instructions.id+code_arr_offset+uint64(wordIndex)]
if w.IsSentinel() {
ch.line++
continue
@@ 131,20 131,32 @@ func (ch Chunk) Execute(vm *VirtualMachine) {
}
}
-func (ch Chunk) execTagIndex(vm *VirtualMachine, tag byte, idx int) {
- literals := ch.ReviveLits(vm)
- // fmt.Println("Executing chunk tag:", tag)
+func (ch RhumbChunk) execTagIndex(vm *VirtualMachine, tag byte, idx int) {
+ var (
+ literals WordArray = ch.ReviveLits(vm)
+ lit word.Word
+ )
switch tag {
case TAG_VALUE_LITERAL:
- vm.AddLiteralToStack(literals.Get(vm, idx))
+ lit = literals.Get(vm, idx)
+ fmt.Println("Executing literal tag:", lit.Debug())
+ vm.AddLiteralToStack(lit)
case TAG_LOCAL_REQUEST:
- vm.SubmitLocalRequest(literals.Get(vm, idx))
+ lit = literals.Get(vm, idx)
+ fmt.Println("Executing local tag:", lit.Debug())
+ vm.SubmitLocalRequest(lit)
case TAG_INNER_REQUEST:
- vm.SubmitInnerRequest(literals.Get(vm, idx))
+ lit = literals.Get(vm, idx)
+ fmt.Println("Executing inner tag:", lit.Debug())
+ vm.SubmitInnerRequest(lit)
case TAG_UNDER_REQUEST:
- vm.SubmitUnderRequest(literals.Get(vm, idx))
+ lit = literals.Get(vm, idx)
+ fmt.Println("Executing under tag:", lit.Debug())
+ vm.SubmitUnderRequest(lit)
case TAG_OUTER_REQUEST:
- vm.SubmitOuterRequest(literals.Get(vm, idx))
+ lit = literals.Get(vm, idx)
+ fmt.Println("Executing outer tag:", lit.Debug())
+ vm.SubmitOuterRequest(lit)
// case TAG_EVENT_REQUEST:
// vm.SubmitEventRequest(literals.Get(idx))
// case TAG_REPLY_REQUEST:
@@ 154,7 166,7 @@ func (ch Chunk) execTagIndex(vm *VirtualMachine, tag byte, idx int) {
}
}
-func (ch Chunk) Disassemble(vm *VirtualMachine) {
+func (ch RhumbChunk) Disassemble(vm *VirtualMachine) {
fmt.Println("============= Chunk =============")
var line int
instructions := ch.ReviveInstrs(vm)
@@ 170,7 182,7 @@ func (ch Chunk) Disassemble(vm *VirtualMachine) {
}
}
-func (ch Chunk) DisassembleCode(vm *VirtualMachine, currentLine, currentOffset int, bufPtr *[]byte) (int, int) {
+func (ch RhumbChunk) DisassembleCode(vm *VirtualMachine, currentLine, currentOffset int, bufPtr *[]byte) (int, int) {
buf := *bufPtr
fmt.Printf("%04d ", currentOffset)
var recurse func(l, o, i int) (int, int)
M internal/vm/descriptor.go => internal/vm/descriptor.go +33 -23
@@ 5,43 5,53 @@ import "git.sr.ht/~madcapjake/grhumb/internal/word"
// type Descriptor struct {
// Mark Word // immutable, mutable, submap
// Name Word // address to TextMap
+// Req Word // requirement linked list
+// Dep Word // dependency linked list
// Data Word // constant, field offset, or
// }
const (
- desc_name_offset uint64 = 1
- desc_data_offset uint64 = 2
+ desc_nme_offset uint64 = 1
+ desc_req_offset uint64 = 2
+ desc_dep_offset uint64 = 3
+ desc_dat_offset uint64 = 4
)
type Descriptor struct {
- vm *VirtualMachine
- id uint64
- at []word.Word
-}
-
-func NewDescriptor(
- vm *VirtualMachine,
- name word.Word, // string address
- kind uint64,
- value word.Word,
-) Descriptor {
- descWords := make([]word.Word, 0, 2)
- descWords = append(descWords, word.Word(kind))
- descWords = append(descWords, name)
- descWords = append(descWords, value)
- loc, _ := vm.ReAllocate(descWords...)
- return Descriptor{vm, loc, vm.heap[loc : loc+2]}
+ Id uint64
}
func ReviveDescriptor(vm *VirtualMachine, addr word.Word) Descriptor {
i := addr.AsAddr()
- mark := vm.heap[i]
+ mark := vm.Heap[i]
if !(mark.IsDescMark()) {
panic("not a descriptor mark")
}
- name := vm.heap[i+desc_name_offset]
- if !(name.IsAddress()) {
+ nameAddr := vm.Heap[i+desc_nme_offset]
+ if !(nameAddr.IsAddress()) {
panic("desciptor name word is not an address")
}
- return Descriptor{vm, i, vm.heap[i : i+2]}
+ if !(vm.Heap[nameAddr].IsRuneArrayMark()) {
+ panic("descriptor name address does not point to rune array")
+ }
+
+ return Descriptor{i}
+}
+
+func (d Descriptor) Name(vm *VirtualMachine) string {
+ nameAddr := vm.Heap[d.Id+desc_nme_offset]
+ if !(nameAddr.IsAddress()) {
+ panic("desciptor name word is not an address")
+ }
+ addr := nameAddr.AsAddr()
+ pointedAt := vm.Heap[addr]
+ if !(pointedAt.IsRuneArrayMark()) {
+ panic("word provided does not point to a rune array")
+ }
+ name := ReviveRuneArray(vm, addr)
+ return name.String(vm)
+}
+
+func (d Descriptor) Data(vm *VirtualMachine) word.Word {
+ return vm.Heap[d.Id+desc_dat_offset]
}
A internal/vm/legend-list.go => internal/vm/legend-list.go +37 -0
@@ 0,0 1,37 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewListLegend(virtualMachine *VirtualMachine) Legend {
+ words := make([]word.Word, 0, 8)
+ init_size := uint32(lgd_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.LIST_LGD),
+ /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend
+ /* Sweep: */ word.FromAddress(0),
+ /* Size: */ word.FromInt(init_size),
+ /* Length: */ word.FromInt(0),
+ /* ReqLink: */ word.FromAddress(0),
+ /* DepLink: */ word.FromAddress(0),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Legend{Id: loc}
+}
+
+func ReviveListLegend(virtualMachine *VirtualMachine, addr word.Word) Legend {
+ i := addr.AsAddr()
+ CheckBaseLegendWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsListLegendMark() },
+ i,
+ )
+ if !(virtualMachine.Heap[i+lgd_dat_offset].IsAddress()) {
+ panic("list array word is not an address")
+ }
+ return Legend{Id: i}
+}
A internal/vm/legend-meta.go => internal/vm/legend-meta.go +34 -0
@@ 0,0 1,34 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewMetaLegend(virtualMachine *VirtualMachine) Legend {
+ words := make([]word.Word, 0, 8)
+ init_size := uint32(lgd_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.LIST_LGD),
+ /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend
+ /* Sweep: */ word.FromAddress(0),
+ /* Size: */ word.FromInt(init_size),
+ /* Length: */ word.FromInt(0),
+ /* ReqLink: */ word.FromAddress(0),
+ /* DepLink: */ word.FromAddress(0),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Legend{Id: loc}
+}
+
+func ReviveMetaLegend(virtualMachine *VirtualMachine, addr word.Word) Legend {
+ i := addr.AsAddr()
+ CheckBaseLegendWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsMetaLegendMark() },
+ i,
+ )
+ return Legend{Id: i}
+}
A internal/vm/legend-routine.go => internal/vm/legend-routine.go +37 -0
@@ 0,0 1,37 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewRoutLegend(virtualMachine *VirtualMachine) Legend {
+ words := make([]word.Word, 0, 8)
+ init_size := uint32(lgd_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.LIST_LGD),
+ /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend
+ /* Sweep: */ word.FromAddress(0),
+ /* Size: */ word.FromInt(init_size),
+ /* Length: */ word.FromInt(0),
+ /* ReqLink: */ word.FromAddress(0),
+ /* DepLink: */ word.FromAddress(0),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Legend{Id: loc}
+}
+
+func ReviveRoutLegend(virtualMachine *VirtualMachine, addr word.Word) Legend {
+ i := addr.AsAddr()
+ CheckBaseLegendWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsRoutLegendMark() },
+ i,
+ )
+ if !(virtualMachine.Heap[i+lgd_dat_offset].IsAddress()) {
+ panic("routine chunk word is not an address")
+ }
+ return Legend{Id: i}
+}
A internal/vm/legend-selector.go => internal/vm/legend-selector.go +37 -0
@@ 0,0 1,37 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewSeleLegend(virtualMachine *VirtualMachine) Legend {
+ words := make([]word.Word, 0, 8)
+ init_size := uint32(lgd_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.LIST_LGD),
+ /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend
+ /* Sweep: */ word.FromAddress(0),
+ /* Size: */ word.FromInt(init_size),
+ /* Length: */ word.FromInt(0),
+ /* ReqLink: */ word.FromAddress(0),
+ /* DepLink: */ word.FromAddress(0),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Legend{Id: loc}
+}
+
+func ReviveSeleLegend(virtualMachine *VirtualMachine, addr word.Word) Legend {
+ i := addr.AsAddr()
+ CheckBaseLegendWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsSeleLegendMark() },
+ i,
+ )
+ if !(virtualMachine.Heap[i+lgd_dat_offset].IsAddress()) {
+ panic("selector chunk word is not an address")
+ }
+ return Legend{Id: i}
+}
A internal/vm/legend-text.go => internal/vm/legend-text.go +37 -0
@@ 0,0 1,37 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewTextLegend(virtualMachine *VirtualMachine) Legend {
+ words := make([]word.Word, 0, 8)
+ init_size := uint32(lgd_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.TEXT_LGD),
+ /* Legend: */ word.FromAddress(0), // TODO: Implement Meta Legend
+ /* Sweep: */ word.FromAddress(0),
+ /* Size: */ word.FromInt(init_size),
+ /* Length: */ word.FromInt(0),
+ /* ReqLink: */ word.FromAddress(0),
+ /* DepLink: */ word.FromAddress(0),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Legend{Id: loc}
+}
+
+func ReviveTextLegend(virtualMachine *VirtualMachine, addr word.Word) Legend {
+ i := addr.AsAddr()
+ CheckBaseLegendWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsTextLegendMark() },
+ i,
+ )
+ if !(virtualMachine.Heap[i+lgd_dat_offset].IsAddress()) {
+ panic("text array word is not an address")
+ }
+ return Legend{Id: i}
+}
M internal/vm/legend.go => internal/vm/legend.go +88 -143
@@ 1,164 1,109 @@
package vm
-import "git.sr.ht/~madcapjake/grhumb/internal/word"
+import (
+ "fmt"
-// type Legend struct {
-// Mark Word
-// MetaLegend Word
-// }
-
-// type BaseMapLegend struct {
-// Legend
-// TrashSweep Word
-// Size Word
-// Length Word
-// ReqLink Word // pointer, circular dependency list
-// DepLink Word // pointer, circular dependency list
-// }
-
-// type MainMapLegend struct {
-// BaseMapLegend
-// Field []Descriptor
-// }
-
-// type ListMapLegend struct {
-// BaseMapLegend
-// Items Word
-// Field []Descriptor
-// }
-
-// type TextMapLegend struct {
-// BaseMapLegend
-// Runes Word
-// Field []Descriptor
-// }
-
-// type FuncMapLegend struct {
-// BaseMapLegend
-// Chunk Word
-// Field []Descriptor
-// }
-
-// type MetaMapLegend struct {
-// BaseMapLegend
-// Field []Descriptor
-// }
-
-type MainMapLegend []word.Word
-type ListMapLegend []word.Word
-type TextMapLegend []word.Word
-type FuncMapLegend []word.Word
-type MetaMapLegend []word.Word
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
const (
- base_lgd_offset uint64 = 1
- base_swp_offset uint64 = 2
- base_sze_offset uint64 = 3
- base_len_offset uint64 = 4
- base_req_offset uint64 = 5
- base_dep_offset uint64 = 6
- main_fld_offset uint64 = 7
- text_arr_offset uint64 = 8
- text_fld_offset uint64 = 9
- rout_chu_offset uint64 = 10
- rout_fld_offset uint64 = 11
+ 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
)
-func NewBaseMapLegend(
- mark word.Word,
- legAddr word.Word,
- length uint32,
- dWords []word.Word,
-) []word.Word {
- words := make([]word.Word, 0, 8)
- words = append(words,
- /* Mark: */ mark,
- /* Legend: */ legAddr,
- /* Sweep: */ word.FromAddress(0),
- /* Size: */ word.FromInt(7+length),
- /* Length: */ word.FromInt(length),
- /* ReqLink: */ word.FromAddress(0),
- /* DepLink: */ word.FromAddress(0),
- )
- words = append(words, dWords...)
- return words
-}
+type Legend struct{ Id uint64 }
-func wordsFromDescriptors(
- d ...Descriptor,
-) (buf []word.Word) {
- // buf = make([]word.Word, 0, len(d)*3)
- // for _, desc := range d {
- // buf = append(buf, d[descIndex]...)
- // }
- return
+func CheckBaseLegendWords(
+ vm *VirtualMachine,
+ isCorrectKindOf func(m word.Word) bool,
+ i uint64,
+) {
+ if !(isCorrectKindOf(vm.Heap[i])) {
+ panic("not correct kind of legend mark")
+ }
+ if !(vm.Heap[i+lgd_lgd_offset].IsAddress()) {
+ panic("meta legend word is not an address")
+ }
+ if !(vm.Heap[i+lgd_swp_offset].IsAddress()) {
+ panic("gc sweep word is not an address")
+ }
+ if !(vm.Heap[i+lgd_sze_offset].IsInteger()) {
+ panic("object size word is not an integer")
+ }
+ if !(vm.Heap[i+lgd_len_offset].IsInteger()) {
+ panic("object length word is not an integer")
+ }
+ if !(vm.Heap[i+lgd_req_offset].IsAddress()) {
+ panic("requirement link word is not an address")
+ }
+ if !(vm.Heap[i+lgd_dep_offset].IsAddress()) {
+ panic("dependency link word is not an address")
+ }
}
-func NewMainMapLegend(
- legAddr word.Word,
- descs ...Descriptor,
-) MainMapLegend {
- descCount := uint32(len(descs))
- dWords := wordsFromDescriptors(descs...)
- return NewBaseMapLegend(
- word.Word(word.MAIN_LGD),
- legAddr,
- descCount,
- dWords,
- )
+func (l Legend) NewDescriptor(
+ vm *VirtualMachine,
+ kind uint64,
+ name RuneArray,
+ offset int,
+) Legend {
+ oldLen := l.Length(vm)
+ oldSze := l.Size(vm)
+ descWords := []word.Word{
+ word.Word(kind),
+ word.FromAddress(name.id),
+ word.FromAddress(0), // TODO: Req link
+ word.FromAddress(0), // TODO: Dep link
+ word.FromInt(uint32(offset)),
+ }
+ loc, _ := vm.Allocate(int(l.Id), int(l.Size(vm)), descWords...)
+ if loc != l.Id {
+ l.Id = loc
+ }
+ l.SetLength(vm, oldLen+1)
+ l.SetSize(vm, oldSze+5)
+ return l
}
-func NewTextMapLegend(
- legAddr word.Word,
- descs ...Descriptor,
-) TextMapLegend {
- descCount := uint32(len(descs))
- dWords := wordsFromDescriptors(descs...)
- return NewBaseMapLegend(
- word.Word(word.TEXT_LGD),
- legAddr,
- descCount,
- dWords,
- )
+// Returns the location of the name provided
+//
+// TODO: Update to return word which is either address or constant
+func (l Legend) Get(vm *VirtualMachine, name RuneArray) (
+ idx int,
+ err error,
+) {
+ // traverse the 5-word descriptors
+ for i := range make([]int, l.Length(vm)*5) {
+ if i%5 == 0 {
+ descMark := vm.Heap[l.Id+lgd_fld_offset+uint64(i)]
+ desc := ReviveDescriptor(vm, descMark)
+ if desc.Name(vm) == name.String(vm) {
+ return int(desc.Data(vm).AsInt()), nil
+ }
+ }
+ }
+
+ return -1, fmt.Errorf("couldn't find word")
}
-func NewRoutMapLegend(
- legAddr word.Word,
- descs ...Descriptor,
-) FuncMapLegend {
- descCount := uint32(len(descs))
- dWords := wordsFromDescriptors(descs...)
- return NewBaseMapLegend(
- word.Word(word.ROUT_LGD),
- legAddr,
- descCount,
- dWords,
- )
+func (l Legend) Length(vm *VirtualMachine) uint32 {
+ return vm.Heap[l.Id+lgd_len_offset].AsInt()
}
-func NewMetaMapLegend(descs ...Descriptor) MetaMapLegend {
- descCount := uint32(len(descs))
- dWords := wordsFromDescriptors(descs...)
- return NewBaseMapLegend(
- word.Word(word.META_LGD),
- word.FromAddress(0),
- descCount,
- dWords,
- )
+func (l Legend) SetLength(vm *VirtualMachine, i uint32) {
+ vm.Heap[l.Id+lgd_len_offset] = word.FromInt(i)
}
-type ArrayLegend struct {
- Mark word.Word
- MetaLegend word.Word
- TrashSweep word.Word
- Field []Descriptor
+func (l Legend) Size(vm *VirtualMachine) uint32 {
+ return vm.Heap[l.Id+lgd_sze_offset].AsInt()
}
-func NewArrayLegend(mark word.Word) ArrayLegend {
- return ArrayLegend{
- Mark: mark,
- MetaLegend: word.FromAddress(0),
- TrashSweep: word.Empty(),
- Field: make([]Descriptor, 0),
- }
+func (l Legend) SetSize(vm *VirtualMachine, i uint32) {
+ vm.Heap[l.Id+lgd_sze_offset] = word.FromInt(i)
}
A internal/vm/map-list.go => internal/vm/map-list.go +29 -0
@@ 0,0 1,29 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewListMap(virtualMachine *VirtualMachine) Map {
+ legend := NewListLegend(virtualMachine)
+ words := make([]word.Word, 0, map_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.LIST_MAP),
+ /* Legend: */ word.Word(legend.Id),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Map{Id: loc}
+}
+
+func ReviveListMap(virtualMachine *VirtualMachine, addr word.Word) Map {
+ i := addr.AsAddr()
+ CheckMapWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsListMapMark() },
+ i,
+ )
+ return Map{Id: i}
+}
A internal/vm/map-meta.go => internal/vm/map-meta.go +29 -0
@@ 0,0 1,29 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewMetaMap(virtualMachine *VirtualMachine) Map {
+ legend := NewMetaLegend(virtualMachine)
+ words := make([]word.Word, 0, map_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.META_MAP),
+ /* Legend: */ word.Word(legend.Id),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Map{Id: loc}
+}
+
+func ReviveMetaMap(virtualMachine *VirtualMachine, addr word.Word) Map {
+ i := addr.AsAddr()
+ CheckMapWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsMetaMapMark() },
+ i,
+ )
+ return Map{Id: i}
+}
A internal/vm/map-routine.go => internal/vm/map-routine.go +29 -0
@@ 0,0 1,29 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewRoutMap(virtualMachine *VirtualMachine) Map {
+ legend := NewRoutLegend(virtualMachine)
+ words := make([]word.Word, 0, map_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.ROUT_MAP),
+ /* Legend: */ word.Word(legend.Id),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Map{Id: loc}
+}
+
+func ReviveRoutMap(virtualMachine *VirtualMachine, addr word.Word) Map {
+ i := addr.AsAddr()
+ CheckMapWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsRoutMapMark() },
+ i,
+ )
+ return Map{Id: i}
+}
A internal/vm/map-selector.go => internal/vm/map-selector.go +29 -0
@@ 0,0 1,29 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewSeleMap(virtualMachine *VirtualMachine) Map {
+ legend := NewSeleLegend(virtualMachine)
+ words := make([]word.Word, 0, map_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.SELE_MAP),
+ /* Legend: */ word.Word(legend.Id),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Map{Id: loc}
+}
+
+func ReviveSeleMap(virtualMachine *VirtualMachine, addr word.Word) Map {
+ i := addr.AsAddr()
+ CheckMapWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsSeleMapMark() },
+ i,
+ )
+ return Map{Id: i}
+}
A internal/vm/map-text.go => internal/vm/map-text.go +29 -0
@@ 0,0 1,29 @@
+package vm
+
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
+
+func NewTextMap(virtualMachine *VirtualMachine) Map {
+ legend := NewTextLegend(virtualMachine)
+ words := make([]word.Word, 0, map_fld_offset)
+ words = append(words,
+ /* Mark: */ word.Word(word.TEXT_MAP),
+ /* Legend: */ word.Word(legend.Id),
+ )
+ loc, err := virtualMachine.ReAllocate(words...)
+ if err != nil {
+ panic("allocation failed")
+ }
+ return Map{Id: loc}
+}
+
+func ReviveTextMap(virtualMachine *VirtualMachine, addr word.Word) Map {
+ i := addr.AsAddr()
+ CheckMapWords(
+ virtualMachine,
+ func(m word.Word) bool { return m.IsTextMapMark() },
+ i,
+ )
+ return Map{Id: i}
+}
M internal/vm/map.go => internal/vm/map.go +118 -22
@@ 1,38 1,134 @@
package vm
-import "git.sr.ht/~madcapjake/grhumb/internal/word"
+import (
+ "git.sr.ht/~madcapjake/grhumb/internal/word"
+)
-// type RhumbMap struct {
-// Mark word.Word
-// Legend word.Word
-// Field []word.Word
-// }
+const (
+ map_lgd_offset uint64 = 1
+ map_fld_offset uint64 = 2
+)
-type RhumbMap []word.Word
+type Map struct{ Id uint64 }
-func NewMap(mark word.Word, legend word.Word, fields ...word.Word) RhumbMap {
- rmap := make([]word.Word, 0, 2+len(fields))
- rmap = append(rmap, mark, legend)
- rmap = append(rmap, fields...)
- return rmap
+func CheckMapWords(
+ vm *VirtualMachine,
+ isCorrectKindOf func(m word.Word) bool,
+ i uint64,
+) {
+ if !(isCorrectKindOf(vm.Heap[i])) {
+ panic("not correct kind of legend mark")
+ }
+ if !(vm.Heap[i+map_lgd_offset].IsAddress()) {
+ panic("map legend word is not an address")
+ }
}
-func NewMainMap(count uint32, legAddr word.Word) RhumbMap {
- return NewMap(word.Word(word.MAIN_MAP), legAddr)
+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 NewListMap(count uint32, legAddr word.Word) RhumbMap {
- return NewMap(word.Word(word.LIST_MAP), legAddr)
+func (m Map) Get(vm *VirtualMachine, name RuneArray) word.Word {
+ legend := m.ReviveLegend(vm)
+ if i, err := legend.Get(vm, name); err != nil {
+ return word.Empty()
+ } else {
+ return m.At(vm, i)
+ }
+
+}
+
+func (m Map) Set(vm *VirtualMachine, name RuneArray, value word.Word) (
+ result Map,
+) {
+ legend := m.ReviveLegend(vm)
+ if i, err := legend.Get(vm, name); err != nil {
+ // New label name
+ result = m.Append(vm, value)
+ legend = legend.NewDescriptor(
+ vm,
+ value.AsDesc(),
+ name,
+ int(result.Length(vm))-1,
+ )
+ if legend.Id != m.Legend(vm) {
+ m.SetLegend(vm, legend.Id)
+ }
+ } else {
+ // Existing label name, i = value offset
+ vm.Heap[m.Locate(vm, i)] = value
+ result = m
+ }
+ return
+}
+
+func (m Map) Locate(vm *VirtualMachine, i int) uint64 {
+ return m.Id + lgd_dat_offset + uint64(i)
+}
+
+func (m Map) At(vm *VirtualMachine, i int) word.Word {
+ mLen := m.Length(vm)
+ if i < 0 || uint32(i) >= mLen {
+ panic("index out of bounds")
+ }
+ return vm.Heap[m.Locate(vm, i)]
+}
+
+func (m Map) Legend(vm *VirtualMachine) uint64 {
+ return vm.Heap[m.Id+map_lgd_offset].AsAddr()
+}
+
+func (m Map) SetLegend(vm *VirtualMachine, l uint64) {
+ vm.Heap[m.Id+map_lgd_offset] = word.FromAddress(l)
+}
+
+func (m Map) Length(vm *VirtualMachine) uint32 {
+ legend := m.ReviveLegend(vm)
+ return legend.Length(vm)
+}
+
+func (m Map) SetLength(vm *VirtualMachine, i uint32) {
+ legend := m.ReviveLegend(vm)
+ legend.SetLength(vm, i)
}
-func NewTextMap(count uint32, legAddr word.Word) RhumbMap {
- return NewMap(word.Word(word.TEXT_MAP), legAddr)
+func (m Map) Size(vm *VirtualMachine) uint32 {
+ legend := m.ReviveLegend(vm)
+ return legend.Size(vm)
}
-func NewRoutMap(count uint32, legAddr word.Word) RhumbMap {
- return NewMap(word.Word(word.ROUT_MAP), legAddr)
+func (m Map) SetSize(vm *VirtualMachine, i uint32) {
+ legend := m.ReviveLegend(vm)
+ legend.SetSize(vm, i)
}
-func NewMetaMap(count uint32, legAddr word.Word) RhumbMap {
- return NewMap(word.Word(word.META_MAP), legAddr)
+func (m Map) ReviveLegend(vm *VirtualMachine) (legend Legend) {
+ legendAddr := vm.Heap[m.Id+map_lgd_offset]
+ switch vm.Heap[legendAddr.AsAddr()] {
+ case word.Word(word.LIST_LGD):
+ legend = ReviveListLegend(vm, legendAddr)
+ case word.Word(word.TEXT_LGD):
+ legend = ReviveTextLegend(vm, legendAddr)
+ case word.Word(word.ROUT_LGD):
+ legend = ReviveRoutLegend(vm, legendAddr)
+ case word.Word(word.SELE_LGD):
+ legend = ReviveSeleLegend(vm, legendAddr)
+ case word.Word(word.META_LGD):
+ legend = ReviveMetaLegend(vm, legendAddr)
+ default:
+ panic("Not a map legend")
+ }
+ return
}
M internal/vm/primitives.go => internal/vm/primitives.go +51 -38
@@ 30,9 30,9 @@ func expBySquaring(x, n uint32) uint32 {
}
func (vm *VirtualMachine) popStack() (popped word.Word) {
- idx := len(vm.stack) - 1
- popped = vm.stack[idx]
- vm.stack = vm.stack[:idx]
+ idx := len(vm.Stack) - 1
+ popped = vm.Stack[idx]
+ vm.Stack = vm.Stack[:idx]
return
}
@@ 40,69 40,81 @@ func (vm *VirtualMachine) gatherTwoInts() (val1, val2 uint32) {
stackVal2 := vm.popStack()
stackVal1 := vm.popStack()
if stackVal1.IsAddress() {
- val1 = vm.heap[stackVal1.AsAddr()].AsInt()
+ val1 = vm.Heap[stackVal1.AsAddr()].AsInt()
} else if stackVal1.IsInteger() {
val1 = stackVal1.AsInt()
}
if stackVal2.IsAddress() {
- val2 = vm.heap[stackVal2.AsAddr()].AsInt()
+ val2 = vm.Heap[stackVal2.AsAddr()].AsInt()
} else if stackVal2.IsInteger() {
val2 = stackVal2.AsInt()
}
return
}
-func (vm *VirtualMachine) assignLabel() {
+func (vm *VirtualMachine) assignScopeLabel(mut bool) {
valWord := vm.popStack()
addrWord := vm.popStack()
- vm.heap[addrWord.AsAddr()] = valWord
+ vm.Heap[addrWord.AsAddr()] = valWord
+}
+
+func (vm *VirtualMachine) assignMapLabel(mut bool) {
+ valWord := vm.popStack()
+ lblWord := vm.popStack()
+ label := ReviveRuneArray(vm, lblWord.AsAddr())
+ lastMap := len(vm.MapScope) - 1
+ vm.MapScope[lastMap] = vm.MapScope[lastMap].Set(vm, label, valWord)
+ logAddedToStack(vm.Stack, fmt.Sprint(label, " set to '", valWord))
}
func (vm *VirtualMachine) addTwoInts() {
val1, val2 := vm.gatherTwoInts()
- vm.stack = append(vm.stack, word.FromInt(val1+val2))
- logAddedToStack(vm.stack, fmt.Sprint(val1, " + ", val2))
+ vm.Stack = append(vm.Stack, word.FromInt(val1+val2))
+ logAddedToStack(vm.Stack, fmt.Sprint(val1, " + ", val2))
}
func (vm *VirtualMachine) subTwoInts() {
val1, val2 := vm.gatherTwoInts()
- vm.stack = append(vm.stack, word.FromInt(val1-val2))
- logAddedToStack(vm.stack, fmt.Sprint(val1, " - ", val2))
+ vm.Stack = append(vm.Stack, word.FromInt(val1-val2))
+ logAddedToStack(vm.Stack, fmt.Sprint(val1, " - ", val2))
}
func (vm *VirtualMachine) mulTwoInts() {
val1, val2 := vm.gatherTwoInts()
- vm.stack = append(vm.stack, word.FromInt(val1*val2))
- logAddedToStack(vm.stack, fmt.Sprint(val1, " x ", val2, " "))
+ vm.Stack = append(vm.Stack, word.FromInt(val1*val2))
+ logAddedToStack(vm.Stack, fmt.Sprint(val1, " x ", val2, " "))
}
func (vm *VirtualMachine) divTwoInts() {
val1, val2 := vm.gatherTwoInts()
- vm.stack = append(vm.stack, word.FromInt(val1/val2))
- logAddedToStack(vm.stack, fmt.Sprint(val1, " / ", val2))
+ vm.Stack = append(vm.Stack, word.FromInt(val1/val2))
+ logAddedToStack(vm.Stack, fmt.Sprint(val1, " / ", val2))
}
func (vm *VirtualMachine) expTwoInts() {
val1, val2 := vm.gatherTwoInts()
- vm.stack = append(vm.stack, word.FromInt(expBySquaring(val1, val2)))
- logAddedToStack(vm.stack, fmt.Sprint(val1, " ^ ", val2))
+ vm.Stack = append(vm.Stack, word.FromInt(expBySquaring(val1, val2)))
+ 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]uint64))
- vm.stack = append(vm.stack, word.Sentinel())
+ vm.LexScope = append(vm.LexScope, make(map[string]uint64))
+ vm.Stack = append(vm.Stack, word.Sentinel())
+ logAddedToStack(vm.Stack, "'('")
}
-// Same as routine
+// New CurrentMap
func (vm *VirtualMachine) beginMap() {
- vm.beginRoutine()
+ vm.MapScope = append(vm.MapScope, NewListMap(vm))
+ vm.Stack = append(vm.Stack, word.Sentinel())
+ logAddedToStack(vm.Stack, "*Map")
}
func (vm *VirtualMachine) unwindToSentinel() error {
- for back := len(vm.stack); back > 0; back-- {
- if vm.stack[back].IsSentinel() {
- vm.stack = vm.stack[:back-1]
+ for back := len(vm.Stack) - 1; back > 0; back-- {
+ if vm.Stack[back].IsSentinel() {
+ vm.Stack = vm.Stack[:back]
return nil
}
}
@@ 111,34 123,35 @@ func (vm *VirtualMachine) unwindToSentinel() error {
// Replace all sub stack values with one final result
func (vm *VirtualMachine) endRoutine() {
- stackLen := len(vm.stack)
- last := vm.stack[stackLen-1]
+ stackLen := len(vm.Stack)
+ last := vm.Stack[stackLen-1]
- vm.scope = vm.scope[:len(vm.scope)-1]
+ vm.LexScope = vm.LexScope[:len(vm.LexScope)-1]
if err := vm.unwindToSentinel(); err != nil {
panic(err)
}
- vm.stack = append(vm.stack, last)
+ vm.Stack = append(vm.Stack, last)
+ logAddedToStack(vm.Stack, last.Debug())
}
-// Delete all sub stack values and turn scope into map
+// Delete all sub stack values and place map address on stack
func (vm *VirtualMachine) endMap() {
- scopeCount := len(vm.scope)
- // mapScope := vm.scope[scopeCount-1]
-
- vm.scope = vm.scope[:scopeCount-1]
+ last := len(vm.MapScope) - 1
+ currMap := vm.MapScope[last]
+ if last == 0 {
+ vm.MapScope = nil
+ } else {
+ vm.MapScope = vm.MapScope[:last-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)
+ vm.Stack = append(vm.Stack, word.FromAddress(currMap.Id))
+ logAddedToStack(vm.Stack, fmt.Sprint("Map@", currMap.Id))
}
/* Phase 2
M internal/vm/vm.go => internal/vm/vm.go +59 -56
@@ 18,11 18,12 @@ func init() {
}
type VirtualMachine struct {
- heap []word.Word
- free []bool
- stack []word.Word
- scope []map[string]uint64
- CurrentChunk Chunk
+ Heap []word.Word
+ Free []bool
+ Stack []word.Word
+ LexScope []map[string]uint64
+ MapScope []Map
+ CurrentChunk RhumbChunk
}
var DEBUG_WIDTH int = 10
@@ 39,21 40,21 @@ func incCheckNL(inc *int) {
func (vm VirtualMachine) DebugHeap() {
if os.Getenv("RHUMB_VM_DEBUG") == "1" {
vmLogger.Println("Dumping memory...")
- for i := 0; i < len(vm.heap); i++ {
+ for i := 0; i < len(vm.Heap); i++ {
if i > 0 && i%DEBUG_WIDTH == 0 {
fmt.Println()
}
- if vm.free[i] {
+ if vm.Free[i] {
fmt.Printf("{%3v: }", i)
- } else if vm.heap[i].IsRuneArrayMark() {
+ } else if vm.Heap[i].IsRuneArrayMark() {
j := i
- fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
+ fmt.Printf("[%3v: %-9s ]", j, vm.Heap[j].Debug())
incCheckNL(&j)
- fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
+ fmt.Printf("[%3v: %-9s ]", j, vm.Heap[j].Debug())
incCheckNL(&j)
- fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
+ fmt.Printf("[%3v: %-9s ]", j, vm.Heap[j].Debug())
incCheckNL(&j)
- fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
+ fmt.Printf("[%3v: %-9s ]", j, vm.Heap[j].Debug())
incCheckNL(&j)
fmt.Printf("[%3v: ", j)
ra := ReviveRuneArray(&vm, uint64(i))
@@ 82,7 83,7 @@ func (vm VirtualMachine) DebugHeap() {
fmt.Print("]")
i += int(ra.Size(&vm)) - 1
} else {
- fmt.Printf("[%3v: %-9s ]", i, vm.heap[i].Debug())
+ fmt.Printf("[%3v: %-9s ]", i, vm.Heap[i].Debug())
}
}
fmt.Println()
@@ 92,12 93,12 @@ func (vm VirtualMachine) DebugHeap() {
func NewVirtualMachine() *VirtualMachine {
vm := new(VirtualMachine)
const init_heap_len int = 10
- vm.heap = make([]word.Word, 0, init_heap_len)
- vm.free = make([]bool, 0, init_heap_len)
+ vm.Heap = make([]word.Word, 0, init_heap_len)
+ vm.Free = make([]bool, 0, init_heap_len)
vm.ReAllocate(word.Word(word.SENTINEL))
- vm.stack = make([]word.Word, 0)
- vm.scope = make([]map[string]uint64, 0)
- vm.scope = append(vm.scope, make(map[string]uint64))
+ vm.Stack = make([]word.Word, 0)
+ vm.LexScope = make([]map[string]uint64, 0)
+ vm.LexScope = append(vm.LexScope, make(map[string]uint64))
// TODO: convert to actual routine
vm.ResetCurrentChunk()
@@ 120,20 121,20 @@ func (vm *VirtualMachine) ReAllocate(ws ...word.Word) (uint64, error) {
return 0, fmt.Errorf("no words provided")
}
var first, next int
- for first = 0; first < len(obj.free); first += next {
+ for first = 0; first < len(obj.Free); first += next {
next = 0
- if obj.free[first] {
+ if obj.Free[first] {
if size == 1 {
vmLogger.Println("moving word to index:", first)
- obj.heap[first] = ws[0]
- obj.free[first] = false
+ obj.Heap[first] = ws[0]
+ obj.Free[first] = false
obj.DebugHeap()
*vm = obj
return uint64(first), nil
} else {
last := first + size
- for next = range obj.free[first+1 : last] {
- if !(obj.free[next]) {
+ for next = range obj.Free[first+1 : last] {
+ if !(obj.Free[next]) {
next++
break
} else if next == last {
@@ 150,7 151,7 @@ func (vm *VirtualMachine) ReAllocate(ws ...word.Word) (uint64, error) {
}
}
// no available chunk in existing memory locations.
- first = len(obj.heap)
+ first = len(obj.Heap)
vmLogger.Println("moving words to end:", first)
obj = appendRhumb(obj, ws)
*vm = obj
@@ 176,25 177,25 @@ func (vm *VirtualMachine) Allocate(
return 0, fmt.Errorf("no words provided")
}
var i int = lastOldId
- if i == len(obj.free) {
+ if i == len(obj.Free) {
vmLogger.Println("appending words to end:", i)
obj = appendRhumb(obj, ws)
*vm = obj
return uint64(loc), nil
}
- if obj.free[i] {
+ if obj.Free[i] {
if newSize == 1 {
vmLogger.Println("appending word to index:", i)
- obj.heap[i] = ws[0]
- obj.free[i] = false
+ obj.Heap[i] = ws[0]
+ obj.Free[i] = false
obj.DebugHeap()
*vm = obj
return uint64(loc), nil
} else {
last := i + newSize - 1
for i = i + 1; i <= last; i++ {
- if !(obj.free[i]) {
+ if !(obj.Free[i]) {
break
} else if i == last {
first := lastOldId
@@ 210,11 211,11 @@ func (vm *VirtualMachine) Allocate(
// Subsequent memory spots unavailable, search for any
// available memory spot across heap
totalWords := make([]word.Word, 0, oldSize+newSize)
- totalWords = append(totalWords, obj.heap[loc:lastOldId]...)
+ totalWords = append(totalWords, obj.Heap[loc:lastOldId]...)
totalWords = append(totalWords, ws...)
- for f := range obj.free[loc:lastOldId] {
- obj.free[loc+f] = true
+ for f := range obj.Free[loc:lastOldId] {
+ obj.Free[loc+f] = true
}
id, err := obj.ReAllocate(totalWords...)
@@ 225,8 226,8 @@ func (vm *VirtualMachine) Allocate(
// Appends to heap and free slices, used in allocate and reallocate
func appendRhumb(vm VirtualMachine, ws []word.Word) VirtualMachine {
for i := range ws {
- vm.heap = append(vm.heap, ws[i])
- vm.free = append(vm.free, false)
+ vm.Heap = append(vm.Heap, ws[i])
+ vm.Free = append(vm.Free, false)
}
vm.DebugHeap()
return vm
@@ 236,7 237,7 @@ func appendRhumb(vm VirtualMachine, ws []word.Word) VirtualMachine {
// to allocate in the heap. Overwriting memory is possible.
func (vm VirtualMachine) allocInPlace(x, y int, ws ...word.Word) {
for hID, wID := x, 0; hID <= y; hID, wID = hID+1, wID+1 {
- vm.heap[hID], vm.free[hID] = ws[wID], false
+ vm.Heap[hID], vm.Free[hID] = ws[wID], false
}
}
@@ 268,10 269,10 @@ func (vm *VirtualMachine) Disassemble() {
func (vm *VirtualMachine) Execute(lastValueFlag bool) {
vm.CurrentChunk.Execute(vm)
if lastValueFlag {
- if len(vm.stack) == 0 {
+ if len(vm.Stack) == 0 {
fmt.Println("()")
} else {
- fmt.Println(vm.stack[len(vm.stack)-1].AsInt())
+ fmt.Println(vm.Stack[len(vm.Stack)-1].AsInt())
}
}
}
@@ 334,28 335,28 @@ func locateScopeLabel(
// }
func (vm *VirtualMachine) AddLiteralToStack(literal word.Word) {
- vm.stack = append(vm.stack, literal)
- logAddedToStack(vm.stack, literal.Debug())
+ vm.Stack = append(vm.Stack, literal)
+ logAddedToStack(vm.Stack, literal.Debug())
}
// Currently just for lexically traversing the scope
func (vm *VirtualMachine) SubmitLocalRequest(addr word.Word) {
- target := vm.heap[addr.AsAddr()]
+ target := vm.Heap[addr.AsAddr()]
if target.IsRuneArrayMark() {
label := ReviveRuneArray(vm, addr.AsAddr()).String(vm)
- idx, ok := locateScopeLabel(vm.scope, label)
+ idx, ok := locateScopeLabel(vm.LexScope, label)
if ok {
// TODO: Invoke address, skip addrRef
- vm.stack = append(vm.stack, word.FromAddress(idx))
- logAddedToStack(vm.stack, label)
+ vm.Stack = append(vm.Stack, word.FromAddress(idx))
+ logAddedToStack(vm.Stack, label)
} else {
- vm.scope[len(vm.scope)-1][label] = addr.AsAddr()
- vm.stack = append(vm.stack, addr)
- logAddedToStack(vm.stack, label)
+ vm.LexScope[len(vm.LexScope)-1][label] = addr.AsAddr()
+ vm.Stack = append(vm.Stack, addr)
+ logAddedToStack(vm.Stack, label)
}
} else {
- vm.stack = append(vm.stack, target)
- logAddedToStack(vm.stack, target.Debug())
+ vm.Stack = append(vm.Stack, target)
+ logAddedToStack(vm.Stack, target.Debug())
}
}
@@ 377,15 378,17 @@ func (vm *VirtualMachine) SubmitOuterRequest(label word.Word) {
panic("unable to find word for outer request")
}
refId := lits.id + word_arr_offset + uint64(addr)
- refAddr := vm.heap[refId]
- ref := vm.heap[refAddr.AsAddr()]
+ refAddr := vm.Heap[refId]
+ ref := vm.Heap[refAddr.AsAddr()]
if !(ref.IsRuneArrayMark()) {
panic("outer request submitted with non-ra value")
}
text := ReviveRuneArray(vm, refAddr.AsAddr()).String(vm)
switch text {
case ".=", ":=":
- vm.assignLabel()
+ vm.assignScopeLabel(text[0] != '.')
+ case "..", "::":
+ vm.assignMapLabel(text[0] != '.')
case "++":
vm.addTwoInts()
case "--":
@@ 396,13 399,13 @@ func (vm *VirtualMachine) SubmitOuterRequest(label word.Word) {
vm.divTwoInts()
case "^^":
vm.expTwoInts()
- case "[[":
+ case "[":
vm.beginMap()
- case "]]":
+ case "]":
vm.endMap()
- case "((":
+ case "(":
vm.beginRoutine()
- case "))":
+ case ")":
vm.endRoutine()
default:
M internal/word/word.go => internal/word/word.go +73 -32
@@ 31,37 31,39 @@ const SENTINEL uint64 = 0x7F_FE_00_00_00_00_00_00
const MARK_MAP uint64 = 0x7F_FE_40_00_00_00_00_00
-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 ROUT_MAP uint64 = 0x7F_FE_40_40_00_00_00_00
+const LIST_MAP uint64 = 0x7F_FE_40_10_00_00_00_00
+const TEXT_MAP uint64 = 0x7F_FE_40_20_00_00_00_00
+const ROUT_MAP uint64 = 0x7F_FE_40_30_00_00_00_00
+const SELE_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 LIST_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_80_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 ROUT_LGD uint64 = 0x7F_FE_C0_40_00_00_00_00
-const ARRA_LGD uint64 = 0x7F_FE_C0_50_00_00_00_00
+const LIST_LGD uint64 = 0x7F_FE_C0_10_00_00_00_00
+const TEXT_LGD uint64 = 0x7F_FE_C0_20_00_00_00_00
+const ROUT_LGD uint64 = 0x7F_FE_C0_30_00_00_00_00
+const SELE_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 DESC_BLE uint64 = 0x7F_FF_00_10_00_00_00_00
+const DESC_ETY uint64 = 0x7F_FF_00_20_00_00_00_00
+const DESC_INT uint64 = 0x7F_FF_00_30_00_00_00_00
+const DESC_RNE uint64 = 0x7F_FF_00_40_00_00_00_00
+const DESC_SYM uint64 = 0x7F_FF_00_50_00_00_00_00
+const DESC_VER uint64 = 0x7F_FF_00_60_00_00_00_00
+const DESC_DTE uint64 = 0x7F_FF_00_70_00_00_00_00
+const DESC_ADD uint64 = 0x7F_FF_00_80_00_00_00_00
+const DESC_MAP uint64 = 0x7F_FF_00_90_00_00_00_00
+const DESC_FLT uint64 = 0x7F_FF_00_F0_00_00_00_00
const CMP_UNIT uint64 = 0x7F_FF_40_00_00_00_00_00
@@ 70,6 72,8 @@ 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 LINE_NUM uint64 = 0x7F_FF_80_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
@@ 134,6 138,7 @@ 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) IsLineNum() bool { return w.isVal(LINE_NUM) }
func (w Word) IsSentinel() bool { return uint64(w) == SENTINEL }
@@ 144,34 149,36 @@ 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.isMark2(MAIN_MAP) }
func (w Word) IsListMapMark() bool { return w.isMark2(LIST_MAP) }
func (w Word) IsTextMapMark() bool { return w.isMark2(TEXT_MAP) }
-func (w Word) IsFuncMapMark() bool { return w.isMark2(ROUT_MAP) }
+func (w Word) IsRoutMapMark() bool { return w.isMark2(ROUT_MAP) }
+func (w Word) IsSeleMapMark() bool { return w.isMark2(SELE_MAP) }
func (w Word) IsMetaMapMark() bool { return w.isMark2(META_MAP) }
func (w Word) IsArrayMark() bool { return w.isMark(MARK_ARR) }
-func (w Word) IsMainArrayMark() bool { return w.isMark2(MAIN_ARR) }
+func (w Word) IsListArrayMark() bool { return w.isMark2(LIST_ARR) }
func (w Word) IsRuneArrayMark() bool { return w.isMark2(RUNE_ARR) }
func (w Word) IsCodeArrayMark() bool { return w.isMark2(CODE_ARR) }
func (w Word) IsMetaArrayMark() bool { return w.isMark2(META_ARR) }
func (w Word) IsLegendMark() bool { return w.isMark(MARK_LGD) }
-func (w Word) IsMainLegendMark() bool { return w.isMark2(MAIN_LGD) }
func (w Word) IsListLegendMark() bool { return w.isMark2(LIST_LGD) }
func (w Word) IsTextLegendMark() bool { return w.isMark2(TEXT_LGD) }
-func (w Word) IsFuncLegendMark() bool { return w.isMark2(ROUT_LGD) }
-func (w Word) IsArraLegendMark() bool { return w.isMark2(ARRA_LGD) }
+func (w Word) IsRoutLegendMark() bool { return w.isMark2(ROUT_LGD) }
+func (w Word) IsSeleLegendMark() bool { return w.isMark2(SELE_LGD) }
func (w Word) IsMetaLegendMark() bool { return w.isMark2(META_LGD) }
func (w Word) IsDescMark() bool { return w.isMark(MARK_DES) }
-func (w Word) IsIntegerDescMark() bool { return w.isMark2(DES_NUMB) }
-func (w Word) IsFloatDescMark() bool { return w.isMark2(DES_FLOA) }
-func (w Word) IsBoolDescMark() bool { return w.isMark2(DES_BOOL) }
-func (w Word) IsRuneDescMark() bool { return w.isMark2(DES_RUNE) }
-func (w Word) IsSymbolDescMark() bool { return w.isMark2(DES_SYMB) }
-func (w Word) IsDateDescMark() bool { return w.isMark2(DES_DATE) }
-func (w Word) IsAddressDescMark() bool { return w.isMark2(DES_ADDR) }
+func (w Word) IsBooleanDescMark() bool { return w.isMark2(DESC_BLE) }
+func (w Word) IsEmptyDescMark() bool { return w.isMark2(DESC_ETY) }
+func (w Word) IsIntegerDescMark() bool { return w.isMark2(DESC_INT) }
+func (w Word) IsRuneDescMark() bool { return w.isMark2(DESC_RNE) }
+func (w Word) IsSymbolDescMark() bool { return w.isMark2(DESC_SYM) }
+func (w Word) IsVersionDescMark() bool { return w.isMark2(DESC_VER) }
+func (w Word) IsDateDescMark() bool { return w.isMark2(DESC_DTE) }
+func (w Word) IsAddressDescMark() bool { return w.isMark2(DESC_ADD) }
+func (w Word) IsMapDescMark() bool { return w.isMark2(DESC_MAP) }
+func (w Word) IsFloatDescMark() bool { return w.isMark2(DESC_FLT) }
func (w Word) IsCmpUnit() bool { return w.isMark(CMP_UNIT) }
@@ 199,11 206,11 @@ func (w Word) Debug() string {
return "MAP MARK"
} else if w.IsCodeArrayMark() {
return "CODE MARK"
- } else if w.IsMainArrayMark() {
+ } else if w.IsListArrayMark() {
return "LIST MARK"
} else if w.IsRuneArrayMark() {
return "RUNE MARK"
- } else if w.IsFuncMapMark() {
+ } else if w.IsRoutMapMark() {
return "ROUTINE"
} else if w.IsCmpUnit() {
return "CMPUNIT"
@@ 264,6 271,38 @@ func (x Word) Equals(y Word) bool {
// 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) AsDesc() uint64 {
+ if w.IsNAN() {
+ return DESC_FLT
+ } else if w.IsTrue() {
+ return DESC_BLE
+ } else if w.IsFalse() {
+ return DESC_BLE
+ } else if w.IsEmpty() {
+ return DESC_ETY
+ } else if w.IsInteger() {
+ return DESC_INT
+ } else if w.IsRune() {
+ return DESC_RNE
+ } else if w.IsSym() {
+ return DESC_SYM
+ } else if w.IsAddress() { // must trigger before IsFloat for unknown reasons
+ return DESC_ADD
+ } else if w.IsFloat() {
+ return DESC_FLT
+ } else if w.IsMapMark() {
+ return DESC_MAP
+ } else if w.IsArrayMark() {
+ panic("Array mark cannot be placed as value")
+ } else if w.IsCmpUnit() {
+ panic("CompUnit cannot be placed as value")
+ } else if w.IsSentinel() {
+ panic("Sentinel cannot be placed as value")
+ } else {
+ panic("Unknown value provided")
+ }
+}
+
func (w Word) AsBool() bool {
switch uint64(w) {
case VAL_TRUE:
@@ 288,3 327,5 @@ 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 }
+
+func (w Word) AsLineNum() uint32 { return uint32(uint64(w) & ^LINE_NUM) }