M internal/generator/visitor.go => internal/generator/visitor.go +7 -11
@@ 99,11 99,7 @@ func (v *RhumbVisitor) VisitMutableLabel(ctx *P.MutableLabelContext) interface{}
func (v *RhumbVisitor) VisitLabelLiteral(ctx *P.LabelLiteralContext) interface{} {
var (
text string = ctx.GetText()
- ra vm.RuneArray = vm.NewRuneArray(
- &v.vm,
- word.FromAddress(0),
- vm.RuneWords(text)...,
- )
+ ra vm.RuneArray = vm.NewRuneArray(&v.vm, word.FromAddress(0), []rune(text)...)
)
logger.Println("label:", text)
v.vm.WriteCodeToMain(
@@ 127,7 123,7 @@ func (v *RhumbVisitor) VisitAssignment(ctx *P.AssignmentContext) interface{} {
// TODO: check for a matching subroutine and invoke
// TODO: check for matching outer scoped label
- ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), vm.RuneWords(text)...)
+ ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), []rune(text)...)
v.vm.WriteCodeToMain(
addr.GetLine(),
@@ 140,7 136,7 @@ func (v *RhumbVisitor) VisitAssignment(ctx *P.AssignmentContext) interface{} {
logger.Printf("addrRef.Accept(v): %v\n", addrRef.Accept(v))
text = addrRef.GetText()
logger.Println("AddressRef:", text)
- ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), vm.RuneWords(text)...)
+ ra = vm.NewRuneArray(&v.vm, word.FromAddress(0), []rune(text)...)
v.vm.WriteCodeToMain(
addrRef.GetStart().GetLine(),
word.FromAddress(int(ra.Id())),
@@ 155,7 151,7 @@ func (v *RhumbVisitor) VisitAssignment(ctx *P.AssignmentContext) interface{} {
ra = vm.NewRuneArray(
&v.vm,
word.FromAddress(0),
- vm.RuneWords(op.GetText())...,
+ []rune(op.GetText())...,
)
v.vm.WriteCodeToMain(
op.GetStart().GetLine(),
@@ 234,7 230,7 @@ func (v *RhumbVisitor) VisitMultiplicative(ctx *P.MultiplicativeContext) interfa
ra vm.RuneArray = vm.NewRuneArray(
&v.vm,
word.FromAddress(0),
- vm.RuneWords(mulOp.GetText())...,
+ []rune(mulOp.GetText())...,
)
)
@@ 258,7 254,7 @@ func (v *RhumbVisitor) VisitAdditive(ctx *P.AdditiveContext) interface{} {
ra vm.RuneArray = vm.NewRuneArray(
&v.vm,
word.FromAddress(0),
- vm.RuneWords(addOp.GetText())...,
+ []rune(addOp.GetText())...,
)
)
@@ 317,7 313,7 @@ func (v *RhumbVisitor) VisitPower(ctx *P.PowerContext) interface{} {
ra vm.RuneArray = vm.NewRuneArray(
&v.vm,
word.FromAddress(0),
- vm.RuneWords(powOp.GetText())...,
+ []rune(powOp.GetText())...,
)
)
for i := range exprs {
M internal/vm/chunk.go => internal/vm/chunk.go +39 -17
@@ 46,29 46,36 @@ func ReviveChunk(vm *VirtualMachine, addr word.Word) Chunk {
func (ch *Chunk) WriteCode(vm *VirtualMachine, line int, codes []Code) {
- instructions := ch.Instructions(vm)
+ instructions := ch.ReviveInstrs(vm)
if line > ch.line {
instructions.SetCodes(vm, true, codes...)
ch.line = line
} else {
instructions.SetCodes(vm, false, codes...)
}
- caId := ch.id + chunk_ca_offset
- if instructions.id != vm.heap[caId].AsAddr() {
- vm.heap[caId] = word.FromAddress(int(instructions.id))
+ if instructions.id != ch.Instructions(vm).AsAddr() {
+ ch.SetInstructionsAddress(vm, instructions.id)
}
}
+func (ch Chunk) SetInstructionsAddress(vm *VirtualMachine, addr uint64) {
+ vm.heap[ch.id+chunk_ca_offset] = word.FromAddress(int(addr))
+}
+
+func (ch Chunk) SetLiteralsAddress(vm *VirtualMachine, addr uint64) {
+ vm.heap[ch.id+chunk_wa_offset] = word.FromAddress(int(addr))
+}
+
func (ch *Chunk) AddLiteral(vm *VirtualMachine, lit word.Word) (uint64, error) {
- literals := ch.Literals(vm)
+ literals := ch.ReviveLits(vm)
existingIndex, err := literals.IndexOf(vm, lit)
if err != nil {
id, err := literals.Append(vm, lit)
if err != nil {
panic("literals append failed")
}
- if id != vm.heap[ch.id+chunk_wa_offset].AsAddr() {
- vm.heap[ch.id+chunk_wa_offset] = word.FromAddress(int(id))
+ if id != ch.Literals(vm).AsAddr() {
+ ch.SetLiteralsAddress(vm, id)
}
return id, err
} else {
@@ 76,23 83,36 @@ func (ch *Chunk) AddLiteral(vm *VirtualMachine, lit word.Word) (uint64, error) {
}
}
-func (ch Chunk) Instructions(vm *VirtualMachine) CodeArray {
- return ReviveCodeArray(vm, vm.heap[ch.id+chunk_ca_offset])
+func (ch Chunk) Instructions(vm *VirtualMachine) word.Word {
+ return vm.heap[ch.id+chunk_ca_offset]
}
-func (ch Chunk) Literals(vm *VirtualMachine) WordArray {
- return ReviveWordArray(vm, vm.heap[ch.id+chunk_wa_offset])
+func (ch Chunk) 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 Chunk) ReviveLits(vm *VirtualMachine) WordArray {
+ return ReviveWordArray(vm, ch.Literals(vm))
}
func (ch Chunk) Execute(vm *VirtualMachine) {
var (
- instructions = ch.Instructions(vm)
- cwLen int = int(instructions.Length(vm))
+ instructions = ch.ReviveInstrs(vm)
+ cwLen int = int(instructions.Size(vm) - code_arr_offset)
idx uint64 = 0
buf []byte = make([]byte, 0, cwLen*8)
)
for wordIndex := 0; wordIndex < cwLen; wordIndex++ {
- instructions.getCodesFromWord(vm, uint64(wordIndex), &buf)
+ w := vm.heap[instructions.id+code_arr_offset+uint64(wordIndex)]
+ if w.IsSentinel() {
+ ch.line++
+ continue
+ }
+ instructions.getCodesFromWord(vm, w, &buf)
for b := range buf {
if buf[b] == 0 {
break
@@ 102,6 122,7 @@ func (ch Chunk) Execute(vm *VirtualMachine) {
if code.IsIndexExtension() {
continue
} else {
+ // FIXME: something is wrong here
ch.execTagIndex(vm, code.Tag(), int(idx))
idx = 0
}
@@ 114,8 135,9 @@ func (ch Chunk) execTagIndex(vm *VirtualMachine, b byte, idx int) {
var (
code Code = Code(b)
tag uint8 = code.Tag()
- literals = ch.Literals(vm)
+ literals = ch.ReviveLits(vm)
)
+ fmt.Println("Executing chunk tag:", tag)
switch tag {
case TAG_VALUE_LITERAL:
vm.AddLiteralToStack(literals.Get(vm, idx))
@@ 137,7 159,7 @@ func (ch Chunk) execTagIndex(vm *VirtualMachine, b byte, idx int) {
func (ch Chunk) Disassemble(vm *VirtualMachine) {
fmt.Println("============= Chunk =============")
var line int
- instructions := ch.Instructions(vm)
+ instructions := ch.ReviveInstrs(vm)
buf := instructions.GetCodes(vm)
for offset := 0; offset < int(instructions.Length(vm)); {
if line < instructions.GetLine(vm, offset) {
@@ 169,7 191,7 @@ func (ch Chunk) DisassembleCode(vm *VirtualMachine, currentLine, currentOffset i
fmt.Printf("%s %d '%v'\n",
Code(buf[o]).String(),
idx,
- ch.Literals(vm).Get(vm, int(idx)).Debug(),
+ ch.ReviveLits(vm).Get(vm, int(idx)).Debug(),
)
return l, o + 1
}
M internal/vm/code_array.go => internal/vm/code_array.go +48 -38
@@ 98,7 98,9 @@ func (ca CodeArray) NewSize(vm *VirtualMachine, newLine bool, cs ...Code) (size
}
} else {
size = origSize
- remainder = ca.getWordCodeCount(vm, uint64(ca.Size(vm)-1))
+ id := ca.id + code_arr_offset + uint64(ca.Size(vm)-1)
+ word := vm.heap[id]
+ remainder = ca.getWordCodeCount(vm, word)
freshLength = newLength - remainder
wholeWords = freshLength / 8
remainder = freshLength % 8
@@ 119,49 121,51 @@ func (ca *CodeArray) SetCodes(
var (
origLen uint64 = uint64(ca.Length(vm))
newLen uint32 = uint32(len(cs))
- byteSize uint32 = 8
- codeID uint32
- initSize uint32
- bs []byte = make([]byte, 0, byteSize)
+ byteSz uint32 = 8
+ codeID int
+ code Code
+ initSz uint32
+ bs []byte = make([]byte, 0, byteSz)
ws []word.Word = make([]word.Word, 0, newLen/8)
+ lastWord word.Word = vm.heap[ca.id+uint64(ca.Size(vm))-1]
)
if newLine {
ws = append(ws, word.Sentinel())
} else {
if ca.lastWordVacancy(vm) {
- ca.getCodesFromWord(vm, uint64(ca.Length(vm))-1, &bs)
- initSize = uint32(len(bs))
- for ; codeID < newLen; codeID++ {
- bs = append(bs, byte(cs[codeID]))
- if initSize+codeID+1 == byteSize {
+ ca.getCodesFromWord(vm, lastWord, &bs)
+ initSz = uint32(len(bs))
+ for codeID, code = range cs {
+ bs = append(bs, byte(code))
+ if initSz+uint32(codeID)+1 == byteSz {
vm.heap[ca.id+ca.Size(vm)] = word.Word(
binary.BigEndian.Uint64(bs))
- bs = make([]byte, 0, byteSize)
+ bs = make([]byte, 0, byteSz)
break
}
}
}
}
- for ; codeID < newLen; codeID++ {
- bs = append(bs, byte(cs[codeID]))
- if codeID+1 == byteSize {
+ for codeID, code = range cs {
+ bs = append(bs, byte(code))
+ if codeID+1 == int(byteSz) {
ws = append(ws, word.Word(binary.BigEndian.Uint64(bs)))
- bs = make([]byte, 0, byteSize)
+ bs = make([]byte, 0, byteSz)
}
}
if len(bs) > 0 {
caLogger.Println(bs)
- for range bs[len(bs):byteSize] {
+ for range bs[len(bs):byteSz] {
bs = append(bs, 0x0)
}
ws = append(ws, word.Word(binary.BigEndian.Uint64(bs)))
}
-
- finalLength := uint32(origLen) + uint32(len(ws))
+ wordsLen := uint32(len(ws))
+ finalLength := uint32(origLen) + wordsLen
ca.SetSize(vm, finalLength+4)
- ca.SetLength(vm, finalLength)
+ ca.SetLength(vm, wordsLen)
newId, _ := vm.Allocate(
int(ca.id),
int(origLen)+int(code_arr_offset),
@@ 174,8 178,15 @@ func (ca *CodeArray) SetCodes(
}
func (ca *CodeArray) lastWordVacancy(vm *VirtualMachine) bool {
- lastIndex := uint64(ca.Length(vm) - 1)
- return ca.getWordCodeCount(vm, lastIndex) != 0
+ var (
+ lastIndex uint64 = uint64(ca.Length(vm) - 1)
+ id uint64 = ca.id + code_arr_offset + lastIndex
+ word word.Word = vm.heap[id]
+ )
+ if word.IsSentinel() {
+ return false
+ }
+ return ca.getWordCodeCount(vm, word) != 0
}
// func (ca *CodeArray) currentIndex(vm *VirtualMachine) int {
@@ 186,11 197,8 @@ func (ca *CodeArray) lastWordVacancy(vm *VirtualMachine) bool {
// }
// }
-func (ca CodeArray) getCodesFromWord(vm *VirtualMachine, wi uint64, b *[]byte) {
- var (
- buf []byte = *b
- word word.Word = vm.heap[ca.id+code_arr_offset+wi]
- )
+func (ca CodeArray) getCodesFromWord(vm *VirtualMachine, word word.Word, b *[]byte) {
+ var buf []byte = *b
if word.IsSentinel() {
panic("cannot get codes from sentinel")
}
@@ 205,12 213,7 @@ func (ca CodeArray) getCodesFromWord(vm *VirtualMachine, wi uint64, b *[]byte) {
*b = buf
}
-func (ca CodeArray) getWordCodeCount(vm *VirtualMachine, wi uint64) int {
- var (
- count int
- id uint64 = ca.id + code_arr_offset + wi
- word word.Word = vm.heap[id]
- )
+func (ca CodeArray) getWordCodeCount(vm *VirtualMachine, word word.Word) (count int) {
if word.IsSentinel() {
panic("cannot get codes from sentinel")
}
@@ 222,15 225,18 @@ func (ca CodeArray) getWordCodeCount(vm *VirtualMachine, wi uint64) int {
}
count = count + 1
}
- return count
+ return
}
func (ca CodeArray) GetCodes(vm *VirtualMachine) []byte {
- cwLen := uint64(ca.Length(vm))
- buf := make([]byte, 0, cwLen*8)
+ var (
+ cwLen uint64 = uint64(ca.Length(vm))
+ buf []byte = make([]byte, 0, cwLen*8)
+ )
for wIndex := code_arr_offset; wIndex < cwLen; wIndex++ {
- if !(vm.heap[ca.id+wIndex].IsSentinel()) {
- ca.getCodesFromWord(vm, wIndex, &buf)
+ w := vm.heap[ca.id+wIndex]
+ if !(w.IsSentinel()) {
+ ca.getCodesFromWord(vm, w, &buf)
}
}
return buf
@@ 245,7 251,11 @@ func (ca *CodeArray) GetLine(vm *VirtualMachine, codeIndex int) (lines int) {
if vm.heap[ca.id+code_arr_offset+i].IsSentinel() {
lines += 1
} else {
- codes += ca.getWordCodeCount(vm, i)
+ var (
+ id uint64 = ca.id + code_arr_offset + i
+ word word.Word = vm.heap[id]
+ )
+ codes += ca.getWordCodeCount(vm, word)
}
}
return
M internal/vm/rune_array.go => internal/vm/rune_array.go +37 -9
@@ 43,18 43,42 @@ func RuneWords(str string) (words []word.Word) {
func NewRuneArray(
vm *VirtualMachine,
legAddr word.Word,
- words ...word.Word,
+ runes ...rune,
) RuneArray {
- wordsLen := uint32(len(words))
- wordsSize := uint32(code_arr_offset) + wordsLen
- raWords := make([]word.Word, 0, wordsSize)
+ var (
+ runesLen uint32 = uint32(len(runes))
+ runesSize uint32 = uint32(code_arr_offset) + runesLen
+ raWords []word.Word = make([]word.Word, 0, runesSize)
+ runeBytes []byte
+ wordBytes []byte
+ offset uint32
+ )
raWords = append(raWords,
/* Mark: */ word.Word(word.RUNE_ARR),
/* Legend: */ legAddr,
- /* Size: */ word.FromInt(wordsSize),
- /* Length: */ word.FromInt(wordsLen),
+ /* Size: */ word.FromInt(runesSize),
+ /* Length: */ word.FromInt(runesLen),
)
- raWords = append(raWords, words...)
+ wordBytes = make([]byte, 8)
+ for i, r := range runes {
+ offset = uint32(i) % 2
+ runeBytes = make([]byte, 4)
+ binary.LittleEndian.PutUint32(runeBytes, uint32(r))
+ if offset == 0 {
+ copy(wordBytes, runeBytes)
+ if i == len(runes)-1 {
+ raWords = append(raWords,
+ word.Word(binary.LittleEndian.Uint64(wordBytes)))
+ }
+ } else {
+ for i, rb := range runeBytes {
+ wordBytes[i+4] = rb
+ }
+ raWords = append(raWords,
+ word.Word(binary.LittleEndian.Uint64(wordBytes)))
+ }
+
+ }
loc, err := vm.ReAllocate(raWords...)
if err != nil {
@@ 63,6 87,10 @@ func NewRuneArray(
return RuneArray{uint64(loc)}
}
+// func GetOrMakeLabelRA(vm *VirtualMachine, text string) RuneArray {
+
+// }
+
func ReviveRuneArray(vm *VirtualMachine, addr word.Word) RuneArray {
i := addr.AsAddr()
mark := vm.heap[i]
@@ 139,8 167,8 @@ func (ra RuneArray) SetRune(vm *VirtualMachine, i uint32, r rune) {
if offset == 0 {
copy(wordBytes, runeBytes)
} else {
- for i := range runeBytes {
- wordBytes[i+4] = runeBytes[i]
+ for i, rb := range runeBytes {
+ wordBytes[i+4] = rb
}
}
vm.heap[id] = word.Word(binary.LittleEndian.Uint64(wordBytes))
M internal/vm/vm.go => internal/vm/vm.go +11 -2
@@ 210,7 210,7 @@ func (vm *VirtualMachine) Disassemble() {
}
func (vm *VirtualMachine) Execute() {
- // vm.main.Execute(vm)
+ vm.main.Execute(vm)
}
func logAddedToStack(stack []word.Word, txt string) {
@@ 308,7 308,16 @@ func (vm *VirtualMachine) SubmitUnderRequest(label word.Word) {
// Used for traversing primitives and compilations
func (vm *VirtualMachine) SubmitOuterRequest(label word.Word) {
// FIXME: locate text
- text := ""
+ addr, err := vm.main.ReviveLits(vm).IndexOf(vm, label)
+ if err != nil {
+ panic("unable to find word for outer request")
+ }
+ ref := vm.heap[vm.main.ReviveInstrs(vm).id+rune_arr_offset+uint64(addr)]
+ if !(ref.IsRuneArrayMark()) {
+ panic("outer request submitted with non-ra value")
+ }
+ text := ReviveRuneArray(vm, ref).String(vm)
+ fmt.Println(text)
switch text {
case ".=", ":=":
vm.assignLabel()
M internal/vm/word_array.go => internal/vm/word_array.go +42 -15
@@ 24,14 24,6 @@ type WordArray struct {
id uint64
}
-func (wa WordArray) Legend(vm *VirtualMachine, i int) word.Word {
- return vm.heap[i]
-}
-
-func (wa WordArray) Length(vm *VirtualMachine) int {
- return int(vm.heap[wa.id+word_arr_offset].AsInt())
-}
-
func NewWordArray(
vm *VirtualMachine,
legAddr word.Word,
@@ 72,26 64,49 @@ func ReviveWordArray(vm *VirtualMachine, addr word.Word) WordArray {
return WordArray{i}
}
-func (wa WordArray) IndexOf(vm *VirtualMachine, w word.Word) (idx int, err error) {
- len := wa.Length(vm)
- for i := range make([]int, len) {
- found := w.Equals(wa.Get(vm, i))
- if found {
- return i, nil
+func (wa WordArray) IndexOf(vm *VirtualMachine, x word.Word) (
+ idx int,
+ err error,
+) {
+ if x.IsAddress() {
+ mkX := vm.heap[x.AsAddr()]
+ if mkX.IsRuneArrayMark() {
+ rax := ReviveRuneArray(vm, x)
+ for i := range make([]int, wa.Length(vm)) {
+ y := wa.Get(vm, i)
+ if y.IsAddress() {
+ mkY := vm.heap[y.AsAddr()]
+ if mkY.IsRuneArrayMark() {
+ ray := ReviveRuneArray(vm, y)
+ if rax.String(vm) == ray.String(vm) {
+ return i, nil
+ }
+ }
+ }
+ }
}
+ } else {
+ for i := range make([]int, wa.Length(vm)) {
+ if x.Equals(wa.Get(vm, i)) {
+ return i, nil
+ }
+ }
+
}
return -1, fmt.Errorf("couldn't find word")
}
func (wa *WordArray) Append(vm *VirtualMachine, newWords ...word.Word) (uint64, error) {
+ oldLen := uint32(wa.Length(vm))
+ newLen := oldLen + uint32(len(newWords))
id, err := vm.Allocate(int(wa.id), wa.Size(vm), newWords...)
if err != nil {
panic("word array append failed")
} else {
if id != wa.id {
- // vm.UpdateAddresses(wa.id, id)
wa.id = id
}
+ wa.SetLength(vm, newLen)
return id, err
}
}
@@ 100,6 115,18 @@ func (wa WordArray) Get(vm *VirtualMachine, i int) word.Word {
return vm.heap[wa.id+word_arr_offset+uint64(i)]
}
+func (wa WordArray) Legend(vm *VirtualMachine, i int) word.Word {
+ return vm.heap[i]
+}
+
+func (wa WordArray) SetLength(vm *VirtualMachine, l uint32) {
+ 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())
+}
+
func (wa WordArray) Size(vm *VirtualMachine) int {
return wa.Length(vm) + 3
}