~madcapjake/rhi

a014098c0f7930377cbce00709245ed3bbc2143e — Jake Russo 1 year, 8 months ago 3af06f3
Flag to print last value
M .vscode/launch.json => .vscode/launch.json +8 -3
@@ 19,15 19,20 @@
            "program": "cmd/rhumb/main.go",
            "args": [
                "line",
                "--disassemble",
                // "--disassemble",
                "--last-value",

                // "foo := 1; bar .= 2; foo ++ bar",


                "foo .= 10",
                "bar .= 3",
                "foo ** bar // 6"
            ],
            "env": {
                "RHUMB_VISITOR_DEBUG": "0",
                "RHUMB_CODE_ARRAY_DEBUG": "1",
                "RHUMB_VM_DEBUG": "1"
                "RHUMB_CODE_ARRAY_DEBUG": "0",
                "RHUMB_VM_DEBUG": "0"
            }
        }


M internal/cli/cli.go => internal/cli/cli.go +14 -5
@@ 17,14 17,18 @@ import (

type visitorContextKey int
type disassembleContextKey int
type lastValueContextKey int

const VisitorCK visitorContextKey = iota
const DisassembleCK disassembleContextKey = iota
const LastValueCK lastValueContextKey = iota

func disassembleFlag(ctx *context.Context, args *[]string) ([]string, error) {
func setupFlags(ctx *context.Context, args *[]string) ([]string, error) {
	flags := flag.NewFlagSet("rhumb", flag.ContinueOnError)
	var disassemble bool
	flags.BoolVar(&disassemble, "disassemble", false, "Disassemble the chunk of code")
	var lastValue bool
	flags.BoolVar(&lastValue, "last-value", false, "Print the last value of the main routine")
	if err := flags.Parse(*args); err != nil {
		return []string{}, err
	}


@@ 34,6 38,11 @@ func disassembleFlag(ctx *context.Context, args *[]string) ([]string, error) {
	} else {
		*ctx = context.WithValue(*ctx, DisassembleCK, false)
	}
	if lastValue {
		*ctx = context.WithValue(*ctx, LastValueCK, true)
	} else {
		*ctx = context.WithValue(*ctx, LastValueCK, false)
	}
	return flags.Args(), nil
}



@@ 53,12 62,12 @@ func parse(ctx context.Context, chars antlr.CharStream) {
	if ctx.Value(DisassembleCK).(bool) {
		vm.Disassemble()
	}
	vm.Execute()
	vm.Execute(ctx.Value(LastValueCK).(bool))
}

func ParseFile(ctx context.Context, args []string) error {
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
	if args, err = setupFlags(&ctx, &args); err != nil {
		return err
	}
	input, err := antlr.NewFileStream(args[1])


@@ 72,7 81,7 @@ func ParseFile(ctx context.Context, args []string) error {

func ParseLines(ctx context.Context, args []string) error {
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
	if args, err = setupFlags(&ctx, &args); err != nil {
		return err
	}
	input := antlr.NewInputStream(strings.Join(args, "\n"))


@@ 82,7 91,7 @@ func ParseLines(ctx context.Context, args []string) error {

func ReadEvalPrintLoop(ctx context.Context, args []string) error {
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
	if args, err = setupFlags(&ctx, &args); err != nil {
		return err
	}
	for {

M internal/generator/visitor.go => internal/generator/visitor.go +1 -1
@@ 19,7 19,7 @@ var viLogger = log.New(io.Discard, "", log.LstdFlags)

func init() {
	if os.Getenv("RHUMB_VISITOR_DEBUG") == "1" {
		viLogger = log.New(os.Stdout, "{VI} ", log.LstdFlags)
		viLogger = log.New(os.Stdout, "{VI} ", log.Ltime)
	}
}


M internal/vm/code_array.go => internal/vm/code_array.go +7 -10
@@ 125,7 125,6 @@ func (ca *CodeArray) SetCodes(
		byteSz     uint32 = 8
		codeID     int
		code       Code
		initSz     uint32
		bs         []byte      = make([]byte, 0, byteSz)
		ws         []word.Word = make([]word.Word, 0, newLen/8)
		lastWordID uint64      = ca.id + uint64(ca.Size(vm)) - 1


@@ 133,24 132,24 @@ func (ca *CodeArray) SetCodes(
	if newLine {
		ws = append(ws, word.Sentinel())
	} else {
		if ca.lastWordVacancy(vm) {
			ca.getCodesFromWord(vm, vm.heap[lastWordID], &bs)
		ca.getCodesFromWord(vm, vm.heap[lastWordID], &bs)
		if len(bs) < 8 {
			vm.free[lastWordID] = true
			origSz--
			initSz = uint32(len(bs))
			tempCS := make([]Code, len(cs))
			copy(tempCS, cs)
			for codeID, code = range tempCS {
				bs = append(bs, byte(code))
				cs = cs[codeID+1:] // shift from main cs var
				if initSz+uint32(codeID)+1 == byteSz {
				if len(bs) == int(byteSz) {
					ws = append(ws,
						word.Word(binary.BigEndian.Uint64(bs)))
					bs = make([]byte, 0, byteSz)
					break
				}
			}

		} else {
			bs = make([]byte, 0, byteSz)
		}
	}
	for codeID, code = range cs {


@@ 169,10 168,8 @@ func (ca *CodeArray) SetCodes(
		bsWord := word.Word(binary.BigEndian.Uint64(bs))
		ws = append(ws, bsWord)
	}
	wordsLen := uint32(len(ws))
	finalLength := uint32(origLen) + newLen
	ca.SetSize(vm, origSz+wordsLen)
	ca.SetLength(vm, finalLength)
	ca.SetSize(vm, origSz+uint32(len(ws)))
	ca.SetLength(vm, uint32(origLen)+newLen)
	newId, _ := vm.Allocate(
		int(ca.id),
		int(origSz),

M internal/vm/vm.go => internal/vm/vm.go +53 -43
@@ 13,7 13,7 @@ var vmLogger = log.New(io.Discard, "", log.LstdFlags)

func init() {
	if os.Getenv("RHUMB_VM_DEBUG") == "1" {
		vmLogger = log.New(os.Stdout, "{VM} ", log.LstdFlags)
		vmLogger = log.New(os.Stdout, "{VM} ", log.Ltime)
	}
}



@@ 37,53 37,56 @@ func incCheckNL(inc *int) {
}

func (vm VirtualMachine) DebugHeap() {
	for i := 0; i < len(vm.heap); i++ {
		if i%DEBUG_WIDTH == 0 {
			fmt.Println()
		}
		if vm.free[i] {
			fmt.Printf("{%3v:           }", i)
		} else if vm.heap[i].IsRuneArrayMark() {
			j := i
			fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
			incCheckNL(&j)
			fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
			incCheckNL(&j)
			fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
			incCheckNL(&j)
			fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
			incCheckNL(&j)
			fmt.Printf("[%3v: ", j)
			ra := ReviveRuneArray(&vm, uint64(i))
			runes := ra.Runes(&vm)
			if len(runes) <= 2 {
				for _, r := range runes {
					fmt.Printf("'%s'", string(r))
					fmt.Print("  ")
				}
			} else {
				for i, r := range runes {
					fmt.Printf("'%s'", string(r))
					if i%2 == 1 {
						fmt.Print("  |")
						incCheckNL(&j)
						fmt.Print("|     ")
					} else {
	if os.Getenv("RHUMB_VM_DEBUG") == "1" {
		vmLogger.Println("Dumping memory...")
		for i := 0; i < len(vm.heap); i++ {
			if i > 0 && i%DEBUG_WIDTH == 0 {
				fmt.Println()
			}
			if vm.free[i] {
				fmt.Printf("{%3v:           }", i)
			} else if vm.heap[i].IsRuneArrayMark() {
				j := i
				fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
				incCheckNL(&j)
				fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
				incCheckNL(&j)
				fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
				incCheckNL(&j)
				fmt.Printf("[%3v: %-9s ]", j, vm.heap[j].Debug())
				incCheckNL(&j)
				fmt.Printf("[%3v: ", j)
				ra := ReviveRuneArray(&vm, uint64(i))
				runes := ra.Runes(&vm)
				if len(runes) <= 2 {
					for _, r := range runes {
						fmt.Printf("'%s'", string(r))
						fmt.Print("  ")
					}
				}
				for range make([]int, (ra.Length(&vm) % 2)) {
					fmt.Print("     ")
				}
				} else {
					for i, r := range runes {
						fmt.Printf("'%s'", string(r))
						if i%2 == 1 {
							fmt.Print("  |")
							incCheckNL(&j)
							fmt.Print("|     ")
						} else {
							fmt.Print("  ")
						}
					}
					for range make([]int, (ra.Length(&vm) % 2)) {
						fmt.Print("     ")
					}

				}
				fmt.Print("]")
				i += int(ra.Size(&vm)) - 1
			} else {
				fmt.Printf("[%3v: %-9s ]", i, vm.heap[i].Debug())
			}
			fmt.Print("]")
			i += int(ra.Size(&vm)) - 1
		} else {
			fmt.Printf("[%3v: %-9s ]", i, vm.heap[i].Debug())
		}
		fmt.Println()
	}
	fmt.Println()
}

func NewVirtualMachine() *VirtualMachine {


@@ 255,8 258,15 @@ func (vm *VirtualMachine) Disassemble() {
	vm.main.Disassemble(vm)
}

func (vm *VirtualMachine) Execute() {
func (vm *VirtualMachine) Execute(lastValueFlag bool) {
	vm.main.Execute(vm)
	if lastValueFlag {
		if len(vm.stack) == 0 {
			fmt.Println("()")
		} else {
			fmt.Println(vm.stack[len(vm.stack)-1].AsInt())
		}
	}
}

func logAddedToStack(stack []word.Word, txt string) {