server
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user