server
Some checks failed
Build / build (push) Failing after 6m4s
Test / build (push) Failing after 6m33s

This commit is contained in:
Chuck Smith
2024-04-02 12:21:41 -04:00
parent 862119e90e
commit 4c9ec5aaaa
77 changed files with 1181 additions and 244 deletions

View File

@@ -6,6 +6,7 @@ import (
"monkey/internal/builtins"
"monkey/internal/code"
"monkey/internal/compiler"
"monkey/internal/context"
"monkey/internal/lexer"
"monkey/internal/object"
"monkey/internal/parser"
@@ -37,7 +38,6 @@ func isTruthy(obj object.Object) bool {
}
}
// executeModule compiles the named module and returns a object.Module object
func executeModule(name string, state *State) (object.Object, error) {
filename := utils.FindModule(name)
if filename == "" {
@@ -66,7 +66,7 @@ func executeModule(name string, state *State) (object.Object, error) {
code := c.Bytecode()
state.Constants = code.Constants
machine := NewWithState(fmt.Sprintf("<module %s>", name), code, state)
machine := New(fmt.Sprintf("<module %s>", name), code, WithState(state))
err = machine.Run()
if err != nil {
return nil, fmt.Errorf("RuntimeError: error loading module '%s'", err)
@@ -113,9 +113,10 @@ func (s *State) ExportedHash() *object.Hash {
}
type VM struct {
Debug bool
Trace bool
debug bool
trace bool
ctx context.Context
state *State
dir string
@@ -150,8 +151,26 @@ func (vm *VM) popFrame() frame {
return vm.frames[vm.fp]
}
type Option func(*VM)
func WithContext(ctx context.Context) Option {
return func(vm *VM) { vm.ctx = ctx }
}
func WithDebug(debug bool) Option {
return func(vm *VM) { vm.debug = debug }
}
func WithState(state *State) Option {
return func(vm *VM) { vm.state = state }
}
func WithTrace(trace bool) Option {
return func(vm *VM) { vm.trace = trace }
}
// New constructs a new monkey-lang bytecode virtual machine
func New(fn string, bytecode *compiler.Bytecode) *VM {
func New(fn string, bytecode *compiler.Bytecode, options ...Option) *VM {
mainFn := object.CompiledFunction{Instructions: bytecode.Instructions}
mainClosure := object.Closure{Fn: &mainFn}
mainFrame := newFrame(&mainClosure, 0)
@@ -159,10 +178,13 @@ func New(fn string, bytecode *compiler.Bytecode) *VM {
frames := make([]frame, maxFrames)
frames[0] = mainFrame
ctx := context.New()
state := NewState()
state.Constants = bytecode.Constants
vm := &VM{
ctx: ctx,
state: state,
stack: make([]object.Object, maxStackSize),
@@ -172,27 +194,8 @@ func New(fn string, bytecode *compiler.Bytecode) *VM {
fp: 1,
}
vm.dir, vm.file = filepath.Split(fn)
return vm
}
func NewWithState(fn string, bytecode *compiler.Bytecode, state *State) *VM {
mainFn := object.CompiledFunction{Instructions: bytecode.Instructions}
mainClosure := object.Closure{Fn: &mainFn}
mainFrame := newFrame(&mainClosure, 0)
frames := make([]frame, maxFrames)
frames[0] = mainFrame
vm := &VM{
state: state,
frames: frames,
fp: 1,
stack: make([]object.Object, maxStackSize),
sp: 0,
for _, option := range options {
option(vm)
}
vm.dir, vm.file = filepath.Split(fn)
@@ -725,7 +728,7 @@ func (vm *VM) callClosure(cl *object.Closure, numArgs int) error {
func (vm *VM) callBuiltin(builtin object.Builtin, numArgs int) error {
args := vm.stack[vm.sp-numArgs : vm.sp]
result := builtin.Fn(args...)
result := builtin.Fn(vm.ctx, args...)
vm.sp = vm.sp - numArgs - 1
if result != nil {
@@ -780,7 +783,7 @@ func (vm *VM) Run() (err error) {
opcodeFreqs = make(map[code.Opcode]int)
)
if vm.Debug {
if vm.debug {
start := time.Now()
defer func() {
end := time.Now().Sub(start)
@@ -807,7 +810,7 @@ func (vm *VM) Run() (err error) {
for err == nil {
op = vm.currentFrame().ReadNextOp()
if vm.Debug {
if vm.debug {
opcodeFreqs[op]++
log.Printf(
"%-25s %-20s\n",
@@ -977,7 +980,7 @@ func (vm *VM) Run() (err error) {
err = fmt.Errorf("unhandled opcode: %s", op)
}
if vm.Trace {
if vm.trace {
log.Printf(
"%-25s [ip=%02d fp=%02d, sp=%02d]",
"", vm.currentFrame().ip, vm.fp-1, vm.sp,