~madcapjake/rhi

a169f91dd102814b0c967008ce631d066eb5d4e1 — Jake Russo 1 year, 9 months ago f03be10
Move logging to env vars & disassemble to a flag
M .vscode/launch.json => .vscode/launch.json +7 -1
@@ 19,10 19,16 @@
            "program": "cmd/rhumb/main.go",
            "args": [
                "line",
                "--disassemble",
                "foo .= 10",
                "bar .= 3",
                "foo ** bar // 6"
            ]
            ],
            "env": {
                "RHUMB_VISITOR_DEBUG": "1",
                "RHUMB_CODE_ARRAY_DEBUG": "1",
                "RHUMB_VM_DEBUG": "1"
            }
        }

    ]

M internal/cli/cli.go => internal/cli/cli.go +40 -13
@@ 4,6 4,7 @@ import (
	"bufio"
	"context"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"


@@ 15,14 16,30 @@ import (
)

type visitorContextKey int
type disassembleContextKey int

const VisitorCK visitorContextKey = iota
const DisassembleCK disassembleContextKey = iota

func parse(visitor *generator.RhumbVisitor, chars antlr.CharStream) {
	lexer := parser.NewRhumbLexer(chars)
func disassembleFlag(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")
	if err := flags.Parse(*args); err != nil {
		return []string{}, err
	}
	flags.Args()
	if disassemble {
		*ctx = context.WithValue(*ctx, DisassembleCK, true)
	} else {
		*ctx = context.WithValue(*ctx, DisassembleCK, false)
	}
	return flags.Args(), nil
}

func parse(ctx context.Context, chars antlr.CharStream) {
	lexer := parser.NewRhumbLexer(chars)
	stream := antlr.NewCommonTokenStream(lexer, 0)

	p := parser.NewRhumbParser(stream)
	p.AddErrorListener(new(generator.RhumbErrorListener))
	p.AddErrorListener(antlr.NewDiagnosticErrorListener(false))


@@ 30,37 47,47 @@ func parse(visitor *generator.RhumbVisitor, chars antlr.CharStream) {
	// p.SetErrorHandler(antlr.NewBailErrorStrategy())
	// p.BuildParseTrees = true

	tree := p.Sequence()
	visitor.Visit(tree)
	visitor := ctx.Value(VisitorCK).(*generator.RhumbVisitor)
	visitor.Visit(p.Sequence())
	vm := visitor.GetVM()
	vm.Disassemble()
	if ctx.Value(DisassembleCK).(bool) {
		vm.Disassemble()
	}
	vm.Execute()
}

func ParseFile(ctx context.Context, args []string) error {
	fmt.Println("Parsing file...")
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
		return err
	}
	input, err := antlr.NewFileStream(args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating filestream: %s\n", err)
		os.Exit(1)
	}

	parse(ctx.Value(VisitorCK).(*generator.RhumbVisitor), input)
	parse(ctx, input)
	return nil
}

func ParseLines(ctx context.Context, args []string) error {
	fmt.Println("Parsing line...")
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
		return err
	}
	input := antlr.NewInputStream(strings.Join(args, "\n"))
	parse(ctx.Value(VisitorCK).(*generator.RhumbVisitor), input)
	parse(ctx, input)
	return nil
}

func ReadEvalPrintLoop(ctx context.Context, args []string) error {
	fmt.Println("REPL...")
	var err error
	if args, err = disassembleFlag(&ctx, &args); err != nil {
		return err
	}
	for {
		reader := bufio.NewReader(os.Stdin)
		fmt.Print("==>> ")
		fmt.Print("=>> ")
		text, err := reader.ReadString('\n')
		if err != nil {
			if errors.Is(err, io.EOF) {

M internal/generator/visitor.go => internal/generator/visitor.go +109 -103
@@ 16,6 16,12 @@ import (

var logger = log.New(io.Discard, "", log.LstdFlags)

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

type RhumbErrorListener struct {
	*antlr.DefaultErrorListener
}


@@ 52,7 58,7 @@ func (v *RhumbVisitor) GetVM() *vm.VirtualMachine {
}

func (v *RhumbVisitor) Visit(tree antlr.ParseTree) interface{} {
	logger.Printf("visit input type: %s\n", reflect.TypeOf(tree))
	logger.Printf("input type: %s\n", reflect.TypeOf(tree))

	switch t := tree.(type) {
	case *antlr.ErrorNodeImpl:


@@ 67,31 73,31 @@ func (v *RhumbVisitor) Visit(tree antlr.ParseTree) interface{} {

func (v *RhumbVisitor) VisitChildren(node antlr.RuleNode) interface{} {
	for _, n := range node.GetChildren() {
		fmt.Println("Visit child:", reflect.TypeOf(n))
		logger.Println("Visit child:", reflect.TypeOf(n))
		v.Visit(n.(antlr.ParseTree))
	}
	return nil
}

func (v *RhumbVisitor) VisitSequence(ctx *parser.SequenceContext) interface{} {
	fmt.Println("sequence!")
	// fmt.Println(ctx.GetText())
	logger.Println("sequence!")
	// logger.Println(ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitSimple(ctx *parser.SimpleContext) interface{} {
	fmt.Println("simple:", ctx.GetText())
	logger.Println("simple:", ctx.GetText())
	return v.Visit(ctx.GetChild(0).(antlr.ParseTree))
}

func (v *RhumbVisitor) VisitMutableLabel(ctx *parser.MutableLabelContext) interface{} {
	fmt.Println("mutable label:", ctx.GetText())
	logger.Println("mutable label:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLabelLiteral(ctx *parser.LabelLiteralContext) interface{} {
	text := ctx.GetText()
	fmt.Println("label:", text)
	logger.Println("label:", text)
	v.vm.WriteCodeToMain(
		ctx.GetStart().GetLine(),
		vm.NewInstrRef(vm.RefLabel, text, nil),


@@ 101,12 107,12 @@ func (v *RhumbVisitor) VisitLabelLiteral(ctx *parser.LabelLiteralContext) interf
}

func (v *RhumbVisitor) VisitAssignment(ctx *parser.AssignmentContext) interface{} {
	fmt.Println("assignment!")
	logger.Println("assignment!")
	// TODO: implement map assignment
	var text string
	if addr := ctx.GetAddress(); addr != nil {
		text = addr.GetText()
		fmt.Println("Address:", text)
		logger.Println("Address:", text)
		// TODO: check for a matching subroutine and invoke
		// TODO: check for matching outer scoped label
		v.vm.WriteCodeToMain(


@@ 117,19 123,19 @@ func (v *RhumbVisitor) VisitAssignment(ctx *parser.AssignmentContext) interface{
	} else {
		// FIXME: make this work as a reference
		addrRef := ctx.GetAddressRef()
		fmt.Printf("addrRef.Accept(v): %v\n", addrRef.Accept(v))
		logger.Printf("addrRef.Accept(v): %v\n", addrRef.Accept(v))
		text = addrRef.GetText()
		fmt.Println("AddressRef:", text)
		logger.Println("AddressRef:", text)
		v.vm.WriteCodeToMain(
			addrRef.GetStart().GetLine(),
			vm.NewInstrRef(vm.RefLabel, text, nil),
			vm.NewLocalRequest,
		)
	}
	fmt.Println("LOCAL:", text)
	fmt.Println("ctx.Expression().Accept...")
	fmt.Println("ctx.Expression().Accept:", ctx.Expression().Accept(v))
	fmt.Println("INNER:")
	logger.Println("LOCAL:", text)
	logger.Println("ctx.Expression().Accept...")
	logger.Println("ctx.Expression().Accept:", ctx.Expression().Accept(v))
	logger.Println("INNER:")
	assignOp := ctx.AssignmentOp()
	v.vm.WriteCodeToMain(
		assignOp.GetStart().GetLine(),


@@ 140,8 146,8 @@ func (v *RhumbVisitor) VisitAssignment(ctx *parser.AssignmentContext) interface{
}

func (v *RhumbVisitor) VisitFloatLiteral(ctx *parser.FloatLiteralContext) interface{} {
	// fmt.Println("float-lit!")
	fmt.Println(ctx.GetText())
	// logger.Println("float-lit!")
	logger.Println(ctx.GetText())
	return v.VisitChildren(ctx)
}



@@ 151,7 157,7 @@ func (v *RhumbVisitor) VisitIntegerLiteral(ctx *parser.IntegerLiteralContext) in
	if err != nil {
		return RhumbReturn{nil, fmt.Errorf("unable to parse int")}
	}
	fmt.Println("VALUE:", val)
	logger.Println("VALUE:", val)
	v.vm.WriteCodeToMain(
		ctx.GetStart().GetLine(),
		vm.NewInstrRef(vm.RefInt, text, val),


@@ 161,47 167,47 @@ func (v *RhumbVisitor) VisitIntegerLiteral(ctx *parser.IntegerLiteralContext) in
}

func (v *RhumbVisitor) VisitStringLiteral(ctx *parser.StringLiteralContext) interface{} {
	fmt.Println("string-lit:", ctx.GetText())
	logger.Println("string-lit:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitReferenceLiteral(ctx *parser.ReferenceLiteralContext) interface{} {
	fmt.Println("ref-lit:", ctx.GetText())
	logger.Println("ref-lit:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitConjunctive(ctx *parser.ConjunctiveContext) interface{} {
	fmt.Println("conj:", ctx.GetText())
	logger.Println("conj:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitAccess(ctx *parser.AccessContext) interface{} {
	fmt.Println("access:", ctx.GetText())
	logger.Println("access:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitApplicative(ctx *parser.ApplicativeContext) interface{} {
	fmt.Println("applicative:", ctx.GetText())
	logger.Println("applicative:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitConditional(ctx *parser.ConditionalContext) interface{} {
	fmt.Println("cond:", ctx.GetText())
	logger.Println("cond:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitPrefix(ctx *parser.PrefixContext) interface{} {
	fmt.Println("prefix:", ctx.GetText())
	logger.Println("prefix:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitComparative(ctx *parser.ComparativeContext) interface{} {
	fmt.Println("compare:", ctx.GetText())
	logger.Println("compare:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitMultiplicative(ctx *parser.MultiplicativeContext) interface{} {
	fmt.Println("multiply:", ctx.GetText())
	logger.Println("multiply:", ctx.GetText())
	exprs := ctx.AllExpression()
	for i := range exprs {
		exprs[i].Accept(v)


@@ 217,7 223,7 @@ func (v *RhumbVisitor) VisitMultiplicative(ctx *parser.MultiplicativeContext) in
}

func (v *RhumbVisitor) VisitAdditive(ctx *parser.AdditiveContext) interface{} {
	fmt.Println("additive:", ctx.GetText())
	logger.Println("additive:", ctx.GetText())
	exprs := ctx.AllExpression()
	for i := range exprs {
		exprs[i].Accept(v)


@@ 233,42 239,42 @@ func (v *RhumbVisitor) VisitAdditive(ctx *parser.AdditiveContext) interface{} {
}

func (v *RhumbVisitor) VisitInvocation(ctx *parser.InvocationContext) interface{} {
	fmt.Println("invoke:", ctx.GetText())
	logger.Println("invoke:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitRoutine(ctx *parser.RoutineContext) interface{} {
	fmt.Println("routine:", ctx.GetText())
	logger.Println("routine:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitDisjunctive(ctx *parser.DisjunctiveContext) interface{} {
	fmt.Println("disjunct:", ctx.GetText())
	logger.Println("disjunct:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIdentity(ctx *parser.IdentityContext) interface{} {
	fmt.Println("identify:", ctx.GetText())
	logger.Println("identify:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitEffect(ctx *parser.EffectContext) interface{} {
	fmt.Println("effect:", ctx.GetText())
	logger.Println("effect:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitMember(ctx *parser.MemberContext) interface{} {
	fmt.Println("member:", ctx.GetText())
	logger.Println("member:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitSelector(ctx *parser.SelectorContext) interface{} {
	fmt.Println("selector:", ctx.GetText())
	logger.Println("selector:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitPower(ctx *parser.PowerContext) interface{} {
	fmt.Println("power:", ctx.GetText())
	logger.Println("power:", ctx.GetText())
	exprs := ctx.AllExpression()
	for i := range exprs {
		exprs[i].Accept(v)


@@ 284,332 290,332 @@ func (v *RhumbVisitor) VisitPower(ctx *parser.PowerContext) interface{} {
}

func (v *RhumbVisitor) VisitMap(ctx *parser.MapContext) interface{} {
	fmt.Println("map:", ctx.GetText())
	logger.Println("map:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitFreeze(ctx *parser.FreezeContext) interface{} {
	fmt.Println("freeze:", ctx.GetText())
	logger.Println("freeze:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitInner(ctx *parser.InnerContext) interface{} {
	fmt.Println("inner:", ctx.GetText())
	logger.Println("inner:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLength(ctx *parser.LengthContext) interface{} {
	fmt.Println("length:", ctx.GetText())
	logger.Println("length:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitFunction(ctx *parser.FunctionContext) interface{} {
	fmt.Println("function:", ctx.GetText())
	logger.Println("function:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitJunction(ctx *parser.JunctionContext) interface{} {
	fmt.Println("junction:", ctx.GetText())
	logger.Println("junction:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitGreaterThan(ctx *parser.GreaterThanContext) interface{} {
	fmt.Println("greater-than:", ctx.GetText())
	logger.Println("greater-than:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitGreaterThanOrEqualTo(ctx *parser.GreaterThanOrEqualToContext) interface{} {
	fmt.Println("greater-than-or-equal-to:", ctx.GetText())
	logger.Println("greater-than-or-equal-to:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLessThan(ctx *parser.LessThanContext) interface{} {
	fmt.Println("less-than:", ctx.GetText())
	logger.Println("less-than:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLessThanOrEqualTo(ctx *parser.LessThanOrEqualToContext) interface{} {
	fmt.Println("less-than-or-equal-to:", ctx.GetText())
	logger.Println("less-than-or-equal-to:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIsEqual(ctx *parser.IsEqualContext) interface{} {
	fmt.Println("is-equal:", ctx.GetText())
	logger.Println("is-equal:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIsLike(ctx *parser.IsLikeContext) interface{} {
	fmt.Println("is-like:", ctx.GetText())
	logger.Println("is-like:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIsIn(ctx *parser.IsInContext) interface{} {
	fmt.Println("is-in:", ctx.GetText())
	logger.Println("is-in:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIsOverlayed(ctx *parser.IsOverlayedContext) interface{} {
	fmt.Println("is-overlayed:", ctx.GetText())
	logger.Println("is-overlayed:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIsTopmost(ctx *parser.IsTopmostContext) interface{} {
	fmt.Println("is-topmost:", ctx.GetText())
	logger.Println("is-topmost:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNotEqual(ctx *parser.NotEqualContext) interface{} {
	fmt.Println("not-equal:", ctx.GetText())
	logger.Println("not-equal:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNotLike(ctx *parser.NotLikeContext) interface{} {
	fmt.Println("not-like:", ctx.GetText())
	logger.Println("not-like:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNotIn(ctx *parser.NotInContext) interface{} {
	fmt.Println("not-in:", ctx.GetText())
	logger.Println("not-in:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNotOverlayed(ctx *parser.NotOverlayedContext) interface{} {
	fmt.Println("not-overlayed:", ctx.GetText())
	logger.Println("not-overlayed:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNotTopmost(ctx *parser.NotTopmostContext) interface{} {
	fmt.Println("not-topmost:", ctx.GetText())
	logger.Println("not-topmost:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitConjunctiveOp(ctx *parser.ConjunctiveOpContext) interface{} {
	fmt.Println("conj-op:", ctx.GetText())
	logger.Println("conj-op:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitDisjunctiveOp(ctx *parser.DisjunctiveOpContext) interface{} {
	fmt.Println("disjunct-op:", ctx.GetText())
	logger.Println("disjunct-op:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitOtherwise(ctx *parser.OtherwiseContext) interface{} {
	fmt.Println("otherwise:", ctx.GetText())
	logger.Println("otherwise:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitDefault(ctx *parser.DefaultContext) interface{} {
	fmt.Println("default:", ctx.GetText())
	logger.Println("default:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitForeach(ctx *parser.ForeachContext) interface{} {
	fmt.Println("for-each:", ctx.GetText())
	logger.Println("for-each:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitWhile(ctx *parser.WhileContext) interface{} {
	fmt.Println("while:", ctx.GetText())
	logger.Println("while:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitThen(ctx *parser.ThenContext) interface{} {
	fmt.Println("then:", ctx.GetText())
	logger.Println("then:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitElse(ctx *parser.ElseContext) interface{} {
	fmt.Println("else:", ctx.GetText())
	logger.Println("else:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitAddition(ctx *parser.AdditionContext) interface{} {
	fmt.Println("addition:", ctx.GetText())
	logger.Println("addition:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitDeviation(ctx *parser.DeviationContext) interface{} {
	fmt.Println("deviation:", ctx.GetText())
	logger.Println("deviation:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitSubtraction(ctx *parser.SubtractionContext) interface{} {
	fmt.Println("subtraction:", ctx.GetText())
	logger.Println("subtraction:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitMultiplication(ctx *parser.MultiplicationContext) interface{} {
	fmt.Println("mupltication:", ctx.GetText())
	logger.Println("mupltication:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitDivision(ctx *parser.DivisionContext) interface{} {
	fmt.Println("division:", ctx.GetText())
	logger.Println("division:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitIntegerDivision(ctx *parser.IntegerDivisionContext) interface{} {
	fmt.Println("int-division:", ctx.GetText())
	logger.Println("int-division:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitModulo(ctx *parser.ModuloContext) interface{} {
	fmt.Println("modulo:", ctx.GetText())
	logger.Println("modulo:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitBind(ctx *parser.BindContext) interface{} {
	fmt.Println("bind:", ctx.GetText())
	logger.Println("bind:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitExponent(ctx *parser.ExponentContext) interface{} {
	fmt.Println("exponenet:", ctx.GetText())
	logger.Println("exponenet:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitRootExtraction(ctx *parser.RootExtractionContext) interface{} {
	fmt.Println("root-extract:", ctx.GetText())
	logger.Println("root-extract:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitScientific(ctx *parser.ScientificContext) interface{} {
	fmt.Println("scientific:", ctx.GetText())
	logger.Println("scientific:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitImmutablePair(ctx *parser.ImmutablePairContext) interface{} {
	fmt.Println("immutable-pair:", ctx.GetText())
	logger.Println("immutable-pair:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitImmutableLabel(ctx *parser.ImmutableLabelContext) interface{} {
	fmt.Println("immutable-label:", ctx.GetText())
	logger.Println("immutable-label:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitMutablePair(ctx *parser.MutablePairContext) interface{} {
	fmt.Println("mutable-pair:", ctx.GetText())
	logger.Println("mutable-pair:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNumericalNegate(ctx *parser.NumericalNegateContext) interface{} {
	fmt.Println("numerical-negate:", ctx.GetText())
	logger.Println("numerical-negate:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitOuterScope(ctx *parser.OuterScopeContext) interface{} {
	fmt.Println("outer-scope:", ctx.GetText())
	logger.Println("outer-scope:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLogicalNegate(ctx *parser.LogicalNegateContext) interface{} {
	fmt.Println("logical-negate:", ctx.GetText())
	logger.Println("logical-negate:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitAssert(ctx *parser.AssertContext) interface{} {
	fmt.Println("assert:", ctx.GetText())
	logger.Println("assert:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitArgument(ctx *parser.ArgumentContext) interface{} {
	fmt.Println("argument:", ctx.GetText())
	logger.Println("argument:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitSlurpSpread(ctx *parser.SlurpSpreadContext) interface{} {
	fmt.Println("slurp-spread:", ctx.GetText())
	logger.Println("slurp-spread:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitBaseClone(ctx *parser.BaseCloneContext) interface{} {
	fmt.Println("base-clone:", ctx.GetText())
	logger.Println("base-clone:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNumericalPosit(ctx *parser.NumericalPositContext) interface{} {
	fmt.Println("numerical-posit:", ctx.GetText())
	logger.Println("numerical-posit:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLogicalPosit(ctx *parser.LogicalPositContext) interface{} {
	fmt.Println("logical-posit:", ctx.GetText())
	logger.Println("logical-posit:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitOverlay(ctx *parser.OverlayContext) interface{} {
	fmt.Println("overlay:", ctx.GetText())
	logger.Println("overlay:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitExistentialPosit(ctx *parser.ExistentialPositContext) interface{} {
	fmt.Println("existential-posit:", ctx.GetText())
	logger.Println("existential-posit:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitImmutableDestruct(ctx *parser.ImmutableDestructContext) interface{} {
	fmt.Println("immutable-destruct:", ctx.GetText())
	logger.Println("immutable-destruct:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitMutableDestruct(ctx *parser.MutableDestructContext) interface{} {
	fmt.Println("mutable-destruct:", ctx.GetText())
	logger.Println("mutable-destruct:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNestedLabel(ctx *parser.NestedLabelContext) interface{} {
	fmt.Println("nested-label:", ctx.GetText())
	logger.Println("nested-label:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNestedOverlay(ctx *parser.NestedOverlayContext) interface{} {
	fmt.Println("nested-overlay:", ctx.GetText())
	logger.Println("nested-overlay:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitRange(ctx *parser.RangeContext) interface{} {
	fmt.Println("range:", ctx.GetText())
	logger.Println("range:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitString(ctx *parser.StringContext) interface{} {
	fmt.Println("string:", ctx.GetText())
	logger.Println("string:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitLabelInterp(ctx *parser.LabelInterpContext) interface{} {
	fmt.Println("label-interp!")
	fmt.Println(ctx.GetText())
	logger.Println("label-interp!")
	logger.Println(ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitRoutineInterp(ctx *parser.RoutineInterpContext) interface{} {
	fmt.Println("routine-interp:", ctx.GetText())
	logger.Println("routine-interp:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitSelectorInterp(ctx *parser.SelectorInterpContext) interface{} {
	fmt.Println("selector-interp:", ctx.GetText())
	logger.Println("selector-interp:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitNamedRef(ctx *parser.NamedRefContext) interface{} {
	fmt.Println("named-ref:", ctx.GetText())
	logger.Println("named-ref:", ctx.GetText())
	return ctx.Label().GetText()
}

func (v *RhumbVisitor) VisitFunctionRef(ctx *parser.FunctionRefContext) interface{} {
	fmt.Println("function-ref:", ctx.GetText())
	logger.Println("function-ref:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitComputedRef(ctx *parser.ComputedRefContext) interface{} {
	fmt.Println("computed-ref:", ctx.GetText())
	logger.Println("computed-ref:", ctx.GetText())
	return v.VisitChildren(ctx)
}

func (v *RhumbVisitor) VisitJunctionRef(ctx *parser.JunctionRefContext) interface{} {
	fmt.Println("junction-ref:", ctx.GetText())
	logger.Println("junction-ref:", ctx.GetText())
	return v.VisitChildren(ctx)
}

M internal/vm/chunk.go => internal/vm/chunk.go +7 -3
@@ 31,8 31,12 @@ func (ir InstrRef) equals(other InstrRef) bool {

type Chunk struct {
	instructions CodeArray
	prestack     []InstrRef
	lines        []int

	// FIXME: Find a less memory intensive line tracking system
	lines []int

	// FIXME: Convert to array of refs & literals for true compilation
	prestack []InstrRef
}

func NewChunk(codes, refs []Word) Chunk {


@@ 120,7 124,7 @@ func (ch Chunk) execTagIndex(vm *VirtualMachine, b byte, idx int) {
}

func (ch Chunk) Disassemble() {
	fmt.Println("============= Routine =============")
	fmt.Println("============= Chunk =============")
	var line int
	buf := ch.instructions.GetCodes()
	for offset := 0; offset < ch.instructions.Len(); {

M internal/vm/code_array.go => internal/vm/code_array.go +12 -2
@@ 2,9 2,19 @@ package vm

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"os"
)

var caLogger = log.New(io.Discard, "", log.LstdFlags)

func init() {
	if os.Getenv("RHUMB_CODE_ARRAY_DEBUG") == "1" {
		caLogger = log.New(os.Stdout, "{CA} ", log.LstdFlags)
	}
}

type CodeArray struct {
	Mark      Word
	Legend    Word // Address


@@ 41,7 51,7 @@ func (ca *CodeArray) SetCodes(cs ...Code) {
		}
	}
	if len(bs) > 0 {
		fmt.Println(bs)
		caLogger.Println(bs)
		for range bs[len(bs):byteSize] {
			bs = append(bs, 0x0)
		}

M internal/vm/vm.go => internal/vm/vm.go +19 -6
@@ 1,6 1,19 @@
package vm

import "fmt"
import (
	"fmt"
	"io"
	"log"
	"os"
)

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)
	}
}

type VirtualMachine struct {
	heap  []Word


@@ 40,16 53,16 @@ func (vm *VirtualMachine) Execute() {
}

func logAddedToStack(stack []Word, txt string) {
	fmt.Print("Added ", txt, " to stack: [")
	logStr := fmt.Sprint("Added ", txt, " to stack: [")
	for s := range stack {
		fmt.Print(" ")
		logStr = fmt.Sprint(logStr, " ")
		if s == len(stack)-1 {
			fmt.Print("\033[1m", stack[s].Debug(), "\033[0m")
			logStr = fmt.Sprint(logStr, "\033[1m", stack[s].Debug(), "\033[0m")
		} else {
			fmt.Print(stack[s].Debug())
			logStr = fmt.Sprint(logStr, stack[s].Debug())
		}
	}
	fmt.Println(" ]")
	vmLogger.Println(logStr, " ]")
}

func (vm *VirtualMachine) AddValueToStack(ir InstrRef) {