Skip to content

Commit 06dc53f

Browse files
committed
Byte code loaded and partly executing
1 parent 7a05a3c commit 06dc53f

File tree

3 files changed

+98
-40
lines changed

3 files changed

+98
-40
lines changed

main.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ package main
55
import (
66
"flag"
77
"fmt"
8-
"os"
9-
//"github.com/ncw/gpython/vm"
108
"github.com/ncw/gpython/marshal"
9+
"github.com/ncw/gpython/py"
10+
"github.com/ncw/gpython/vm"
1111
"log"
12+
"os"
1213
"strings"
1314
)
1415

@@ -58,7 +59,8 @@ func main() {
5859
if err != nil {
5960
log.Fatal(err)
6061
}
61-
_ = obj
62-
// fmt.Println(obj)
62+
code := obj.(*py.Code)
63+
v := vm.NewVm()
64+
v.Run(code)
6365

6466
}

py/code.go

+36-35
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@ import (
99
// Code object
1010
type Code struct {
1111
// Object_HEAD
12-
argcount int32 // #arguments, except *args
13-
kwonlyargcount int32 // #keyword only arguments
14-
nlocals int32 // #local variables
15-
stacksize int32 // #entries needed for evaluation stack
16-
flags int32 // CO_..., see below
17-
code Object // instruction opcodes
18-
consts Object // list (constants used)
19-
names Object // list of strings (names used)
20-
varnames Object // tuple of strings (local variable names)
21-
freevars Object // tuple of strings (free variable names)
22-
cellvars Object // tuple of strings (cell variable names)
12+
Argcount int32 // #arguments, except *args
13+
Kwonlyargcount int32 // #keyword only arguments
14+
Nlocals int32 // #local variables
15+
Stacksize int32 // #entries needed for evaluation stack
16+
Flags int32 // CO_..., see below
17+
Code String // instruction opcodes
18+
Consts Tuple // list (constants used)
19+
Names Tuple // list of strings (names used)
20+
Varnames Tuple // tuple of strings (local variable names)
21+
Freevars Tuple // tuple of strings (free variable names)
22+
Cellvars Tuple // tuple of strings (cell variable names)
2323
// The rest doesn't count for hash or comparisons
24-
cell2arg *byte // Maps cell vars which are arguments.
25-
filename Object // unicode (where it was loaded from)
26-
name Object // unicode (name, for reference)
27-
firstlineno int32 // first source line number
28-
lnotab Object // string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details.
24+
Cell2arg *byte // Maps cell vars which are arguments.
25+
Filename String // unicode (where it was loaded from)
26+
Name String // unicode (name, for reference)
27+
Firstlineno int32 // first source line number
28+
Lnotab String // string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details.
2929

30-
weakreflist Object // to support weakrefs to code objects
30+
Weakreflist List // to support weakrefs to code objects
3131
}
3232

3333
var CodeType = NewType("code")
@@ -95,7 +95,7 @@ func all_name_chars(s String) bool {
9595
// Make a new code object
9696
func NewCode(argcount int32, kwonlyargcount int32,
9797
nlocals int32, stacksize int32, flags int32,
98-
code Object, consts_ Object, names_ Object,
98+
code_ Object, consts_ Object, names_ Object,
9999
varnames_ Object, freevars_ Object, cellvars_ Object,
100100
filename_ Object, name_ Object, firstlineno int32,
101101
lnotab_ Object) *Code {
@@ -111,6 +111,7 @@ func NewCode(argcount int32, kwonlyargcount int32,
111111
name := name_.(String)
112112
filename := filename_.(String)
113113
lnotab := lnotab_.(String)
114+
code := code_.(String)
114115

115116
// Check argument types
116117
if argcount < 0 || kwonlyargcount < 0 || nlocals < 0 {
@@ -167,22 +168,22 @@ func NewCode(argcount int32, kwonlyargcount int32,
167168
}
168169

169170
return &Code{
170-
argcount: argcount,
171-
kwonlyargcount: kwonlyargcount,
172-
nlocals: nlocals,
173-
stacksize: stacksize,
174-
flags: flags,
175-
code: code,
176-
consts: consts,
177-
names: names,
178-
varnames: varnames,
179-
freevars: freevars,
180-
cellvars: cellvars,
181-
cell2arg: cell2arg,
182-
filename: filename,
183-
name: name,
184-
firstlineno: firstlineno,
185-
lnotab: lnotab,
186-
weakreflist: nil,
171+
Argcount: argcount,
172+
Kwonlyargcount: kwonlyargcount,
173+
Nlocals: nlocals,
174+
Stacksize: stacksize,
175+
Flags: flags,
176+
Code: code,
177+
Consts: consts,
178+
Names: names,
179+
Varnames: varnames,
180+
Freevars: freevars,
181+
Cellvars: cellvars,
182+
Cell2arg: cell2arg,
183+
Filename: filename,
184+
Name: name,
185+
Firstlineno: firstlineno,
186+
Lnotab: lnotab,
187+
Weakreflist: nil,
187188
}
188189
}

vm/eval.go

+56-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package vm
33

44
import (
5+
"fmt"
56
"github.com/ncw/gpython/py"
67
)
78

@@ -145,11 +146,20 @@ func init() {
145146

146147
// Virtual machine state
147148
type Vm struct {
149+
// Object stack
148150
stack []py.Object
151+
// Current code object
152+
co *py.Code
153+
// Whether ext should be added to the next arg
154+
extended bool
155+
// 16 bit extension for argument for next opcode
156+
ext int32
157+
// Whether we should exit
158+
exit bool
149159
}
150160

151161
// Make a new VM
152-
func NewVM() *Vm {
162+
func NewVm() *Vm {
153163
vm := new(Vm)
154164
vm.stack = make([]py.Object, 0, 1024)
155165
return vm
@@ -416,6 +426,7 @@ func do_MAP_ADD(vm *Vm, i int32) {
416426

417427
// Returns with TOS to the caller of the function.
418428
func do_RETURN_VALUE(vm *Vm, arg int32) {
429+
vm.exit = true
419430
}
420431

421432
// Pops TOS and delegates to it as a subiterator from a generator.
@@ -525,10 +536,12 @@ func do_DELETE_GLOBAL(vm *Vm, namei int32) {
525536

526537
// Pushes co_consts[consti] onto the stack.
527538
func do_LOAD_CONST(vm *Vm, consti int32) {
539+
vm.PUSH(vm.co.Consts[consti])
528540
}
529541

530542
// Pushes the value associated with co_names[namei] onto the stack.
531543
func do_LOAD_NAME(vm *Vm, namei int32) {
544+
vm.PUSH(vm.co.Names[namei])
532545
}
533546

534547
// Creates a tuple consuming count items from the stack, and pushes
@@ -686,6 +699,18 @@ func do_RAISE_VARARGS(vm *Vm, argc int32) {
686699
// function arguments, and the function itself off the stack, and
687700
// pushes the return value.
688701
func do_CALL_FUNCTION(vm *Vm, argc int32) {
702+
nargs := int(argc & 0xFF)
703+
nkwargs := int((argc >> 8) & 0xFF)
704+
p, q := len(vm.stack)-2*nkwargs, len(vm.stack)
705+
kwargs := vm.stack[p:q]
706+
p, q = p-nargs, p
707+
args := vm.stack[p:q]
708+
p, q = p-1, p
709+
fn := vm.stack[p]
710+
fmt.Printf("Call %v with args = %v, kwargs = %v\n", fn, args, kwargs)
711+
// Drop the args off the stack and put return value in
712+
vm.stack = vm.stack[:q]
713+
vm.stack[p] = py.None
689714
}
690715

691716
// Pushes a new function object on the stack. TOS is the code
@@ -713,6 +738,8 @@ func do_BUILD_SLICE(vm *Vm, argc int32) {
713738
// together with the subsequent opcode’s argument, comprise a
714739
// four-byte argument, ext being the two most-significant bytes.
715740
func do_EXTENDED_ARG(vm *Vm, ext int32) {
741+
vm.ext = ext
742+
vm.extended = true
716743
}
717744

718745
// Calls a function. argc is interpreted as in CALL_FUNCTION. The top
@@ -733,3 +760,31 @@ func do_CALL_FUNCTION_KW(vm *Vm, argc int32) {
733760
// keyword and positional arguments.
734761
func do_CALL_FUNCTION_VAR_KW(vm *Vm, argc int32) {
735762
}
763+
764+
// Run the virtual machine on the code object
765+
func (vm *Vm) Run(co *py.Code) {
766+
vm.co = co
767+
ip := 0
768+
var opcode byte
769+
var arg int32
770+
code := co.Code
771+
for !vm.exit {
772+
opcode = code[ip]
773+
ip++
774+
if HAS_ARG(opcode) {
775+
arg = int32(code[ip])
776+
ip++
777+
arg += int32(code[ip] << 8)
778+
ip++
779+
if vm.extended {
780+
arg += vm.ext << 16
781+
}
782+
fmt.Printf("Opcode %d with arg %d\n", opcode, arg)
783+
} else {
784+
fmt.Printf("Opcode %d\n", opcode)
785+
}
786+
vm.extended = false
787+
jumpTable[opcode](vm, arg)
788+
}
789+
// Return something?
790+
}

0 commit comments

Comments
 (0)