Skip to content

Commit 2ee8fad

Browse files
committed
Added primcall instruction
marginally faster, will allow special handling of primitives.
1 parent cdb8c5b commit 2ee8fad

File tree

5 files changed

+117
-60
lines changed

5 files changed

+117
-60
lines changed

code.go

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
opcodeVector // 15
4343
opcodeStruct
4444
opcodeUndefGlobal
45+
opcodePrimCall
4546
)
4647

4748
var symOpClosure = intern("closure")
@@ -54,20 +55,21 @@ var symOpJump = intern("jump")
5455
var symOpJumpFalse = intern("jumpfalse")
5556
var symOpCall = intern("call")
5657
var symOpTailCall = intern("tailcall")
57-
var symOpReturn = intern("return")
58-
var symOpPop = intern("pop")
58+
var symOpPrimCall = intern("primcall")
59+
var symOpReturn = intern("return")
60+
var symOpPop = intern("pop")
5961
var symOpDefGlobal = intern("defglobal")
6062
var symOpUndefGlobal = intern("undefglobal")
6163
var symOpDefMacro = intern("defmacro")
6264
var symOpUse = intern("use")
6365

6466
// Code - compiled Ell bytecode
6567
type Code struct {
66-
name string
67-
ops []int
68-
argc int
69-
defaults []LAny
70-
keys []LAny
68+
name string
69+
ops []int
70+
argc int
71+
defaults []LAny
72+
keys []LAny
7173
}
7274

7375
func newCode(argc int, defaults []LAny, keys []LAny, name string) *Code {
@@ -148,7 +150,7 @@ func (code *Code) signature() string {
148150
}
149151
//the following has no type info
150152
tmp := ""
151-
for i:=0; i<code.argc; i++ {
153+
for i := 0; i < code.argc; i++ {
152154
tmp += " <any>"
153155
}
154156
if code.defaults != nil {
@@ -197,31 +199,27 @@ func (code *Code) decompileInto(buf *bytes.Buffer, indent string, pretty bool) {
197199
for offset < max {
198200
switch code.ops[offset] {
199201
case opcodeLiteral:
200-
//fmt.Printf("%sL%03d:\t(literal %d) \t; %v\n", indent, offset, code.ops[offset+1], constants[code.ops[offset+1]])
201202
buf.WriteString(prefix + "(literal " + write(constants[code.ops[offset+1]]) + ")")
202203
offset += 2
203204
case opcodeDefGlobal:
204-
//fmt.Printf("%sL%03d:\t(global %v)\n", indent, offset, constants[code.ops[offset+1]])
205205
buf.WriteString(prefix + "(defglobal " + write(constants[code.ops[offset+1]]) + ")")
206206
offset += 2
207207
case opcodeCall:
208-
//fmt.Printf("%sL%03d:\t(call %d)\n", indent, offset, code.ops[offset+1])
209208
buf.WriteString(prefix + "(call " + strconv.Itoa(code.ops[offset+1]) + ")")
210209
offset += 2
211210
case opcodeTailCall:
212-
//fmt.Printf("%s%03d:\t(tailcall %d)\n", indent, offset, code.ops[offset+1])
213211
buf.WriteString(prefix + "(tailcall " + strconv.Itoa(code.ops[offset+1]) + ")")
214212
offset += 2
213+
case opcodePrimCall:
214+
buf.WriteString(prefix + "(primcall " + strconv.Itoa(code.ops[offset+1]) + " " + primitives[code.ops[offset+2]].name + ")")
215+
offset += 3
215216
case opcodePop:
216-
//fmt.Printf("%sL%03d:\t(pop)\n", indent, offset)
217217
buf.WriteString(prefix + "(pop)")
218218
offset++
219219
case opcodeReturn:
220-
//fmt.Printf("%sL%03d:\t(return)\n", indent, offset)
221220
buf.WriteString(prefix + "(return)")
222221
offset++
223222
case opcodeClosure:
224-
//fmt.Printf("%sL%03d:\t(closure %v)\n", indent, offset, code.ops[offset+1])
225223
buf.WriteString(prefix + "(closure")
226224
if pretty {
227225
buf.WriteString("\n")
@@ -236,31 +234,24 @@ func (code *Code) decompileInto(buf *bytes.Buffer, indent string, pretty bool) {
236234
buf.WriteString(")")
237235
offset += 2
238236
case opcodeLocal:
239-
//fmt.Printf("%sL%03d:\t(local %d %d)\n", indent, offset, code.ops[offset+1], code.ops[offset+2])
240237
buf.WriteString(prefix + "(local " + strconv.Itoa(code.ops[offset+1]) + " " + strconv.Itoa(code.ops[offset+2]) + ")")
241238
offset += 3
242239
case opcodeGlobal:
243-
//fmt.Printf("%sL%03d:\t(global %v)\n", indent, offset, constants[code.ops[offset+1]])
244240
buf.WriteString(prefix + "(global " + write(constants[code.ops[offset+1]]) + ")")
245241
offset += 2
246242
case opcodeUndefGlobal:
247-
//fmt.Printf("%sL%03d:\t(unglobal %v)\n", indent, offset, constants[code.ops[offset+1]])
248243
buf.WriteString(prefix + "(undefglobal " + write(constants[code.ops[offset+1]]) + ")")
249244
offset += 2
250245
case opcodeDefMacro:
251-
//fmt.Printf("%sL%03d:\t(defmacro%6d ; %v)\n", indent, offset, code.ops[offset+1], constants[code.ops[offset+1]])
252246
buf.WriteString(prefix + "(defmacro " + write(constants[code.ops[offset+1]]) + ")")
253247
offset += 2
254248
case opcodeSetLocal:
255-
//Println("%sL%03d:\t(setlocal %d %d)\n", indent, offset, code.ops[offset+1], code.ops[offset+2])
256249
buf.WriteString(prefix + "(setlocal " + strconv.Itoa(code.ops[offset+1]) + " " + strconv.Itoa(code.ops[offset+2]) + ")")
257250
offset += 3
258251
case opcodeJumpFalse:
259-
//fmt.Printf("%sL%03d:\t(jumpfalse %d)\t; L%03d\n", indent, offset, code.ops[offset+1], code.ops[offset+1] + offset)
260252
buf.WriteString(prefix + "(jumpfalse " + strconv.Itoa(code.ops[offset+1]) + ")")
261253
offset += 2
262254
case opcodeJump:
263-
//fmt.Printf("%sL%03d:\t(jump %d) \t; L%03d\n", indent, offset, code.ops[offset+1], code.ops[offset+1] + offset)
264255
buf.WriteString(prefix + "(jump " + strconv.Itoa(code.ops[offset+1]) + ")")
265256
offset += 2
266257
case opcodeVector:
@@ -363,7 +354,11 @@ func (code *Code) loadOps(lst LAny) error {
363354
}
364355
code.emitSetLocal(i, j)
365356
case symOpGlobal:
366-
code.emitGlobal(cadr(instr))
357+
if sym, ok := cadr(instr).(*LSymbol); ok {
358+
code.emitGlobal(sym)
359+
} else {
360+
return Error(symOpGlobal, " argument 1 not a symbol: ", cadr(instr))
361+
}
367362
case symOpUndefGlobal:
368363
code.emitUndefGlobal(cadr(instr))
369364
case symOpJump:
@@ -413,9 +408,9 @@ func (code *Code) emitLiteral(val LAny) {
413408
code.ops = append(code.ops, putConstant(val))
414409
}
415410

416-
func (code *Code) emitGlobal(sym LAny) {
411+
func (code *Code) emitGlobal(sym *LSymbol) {
417412
code.ops = append(code.ops, opcodeGlobal)
418-
code.ops = append(code.ops, putConstant(sym))
413+
code.ops = append(code.ops, sym.tag)
419414
}
420415
func (code *Code) emitCall(argc int) {
421416
code.ops = append(code.ops, opcodeCall)
@@ -428,6 +423,11 @@ func (code *Code) emitTailCall(argc int) {
428423
code.ops = append(code.ops, opcodeTailCall)
429424
code.ops = append(code.ops, argc)
430425
}
426+
func (code *Code) emitPrimCall(prim *LPrimitive, argc int) {
427+
code.ops = append(code.ops, opcodePrimCall)
428+
code.ops = append(code.ops, prim.idx)
429+
code.ops = append(code.ops, argc)
430+
}
431431
func (code *Code) emitPop() {
432432
code.ops = append(code.ops, opcodePop)
433433
}

compiler.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func compileExpr(code *Code, env *LList, expr LAny, isTail bool, ignoreResult bo
6363
if i, j, ok := calculateLocation(expr, env); ok {
6464
code.emitLocal(i, j)
6565
} else {
66-
code.emitGlobal(expr)
66+
code.emitGlobal(expr.(*LSymbol))
6767
}
6868
if ignoreResult {
6969
code.emitPop()
@@ -383,6 +383,19 @@ func compileFuncall(code *Code, env *LList, fn LAny, args *LList, isTail bool, i
383383
if err != nil {
384384
return err
385385
}
386+
fval := global(fn)
387+
if fval != nil && true {
388+
switch fprim := fval.(type) {
389+
case *LPrimitive:
390+
code.emitPrimCall(fprim, argc)
391+
if ignoreResult {
392+
code.emitPop()
393+
} else if isTail {
394+
code.emitReturn()
395+
}
396+
return nil
397+
}
398+
}
386399
err = compileExpr(code, env, fn, false, false, context)
387400
if err != nil {
388401
return err

ell.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ func initEnvironment() {
8181
defineFunction("concat", ellConcat, "(<list>*) <list>")
8282
defineFunction("reverse", ellReverse, "(<list>) <list>")
8383
defineFunction("flatten", ellFlatten, "(<list>) <list>")
84-
defineFunction("set-car!", ellSetCarBang, "(<list> <any>) <null>") //mutate!
84+
defineFunction("set-car!", ellSetCarBang, "(<list> <any>) <null>") //mutate!
8585
defineFunction("set-cdr!", ellSetCdrBang, "(<list> <list>) <null>") //mutate!
8686

8787
defineFunction("vector?", ellVectorP, "(<any>) <boolean>")
88-
defineFunction("to-vector", ellToVector, "(<any>) <vector>")
88+
defineFunction("to-vector", ellToVector, "(<any>) <vector>")
8989
defineFunction("vector", ellVector, "(<any>*) <vector>")
9090
defineFunction("make-vector", ellMakeVector, "(<number> <any>) <vector>")
9191
defineFunction("vector-set!", ellVectorSetBang, "(<vector> <number> <any>) <null>") //mutate!
@@ -358,7 +358,7 @@ func ellNewline(argv []LAny, argc int) (LAny, error) {
358358
//todo: add the optional output argument like scheme
359359
return nil, ArgcError("newline", "0", argc)
360360
}
361-
fmt.Printf("\n")
361+
fmt.Println("")
362362
return Null, nil
363363
}
364364

@@ -834,14 +834,16 @@ func ellString(argv []LAny, argc int) (LAny, error) {
834834

835835
func ellCar(argv []LAny, argc int) (LAny, error) {
836836
if argc == 1 {
837-
return safeCar(argv[0])
837+
// return safeCar(argv[0])
838+
return car(argv[0]), nil
838839
}
839840
return nil, ArgcError("car", "1", argc)
840841
}
841842

842843
func ellCdr(argv []LAny, argc int) (LAny, error) {
843844
if argc == 1 {
844-
return safeCdr(argv[0])
845+
// return safeCdr(argv[0])
846+
return cdr(argv[0]), nil
845847
}
846848
return nil, ArgcError("cdr", "1", argc)
847849
}

module.go

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import (
2424
var constantsMap = make(map[LAny]int, 0)
2525
var constants = make([]LAny, 0, 1000)
2626
var globals = make([]*binding, 0, 1000)
27+
var globalsMap = make(map[*LSymbol]int, 0)
2728
var macroMap = make(map[LAny]*macro, 0)
29+
var primitives = make([]*LPrimitive, 0, 1000)
2830

2931
func checkInterrupt() bool {
3032
if interrupts != nil {
@@ -51,19 +53,20 @@ func define(name string, obj LAny) {
5153
func defineFunction(name string, fun primitive, signature string) {
5254
sym := intern(name)
5355
if global(sym) != nil {
54-
println("*** Warning: redefining ", name)
56+
println("*** Warning: redefining ", name, " with a primitive")
5557
}
56-
prim := LPrimitive{name, fun, signature}
57-
defGlobal(sym, &prim)
58+
59+
prim := newPrimitive(name, fun, signature)
60+
defGlobal(sym, prim)
5861
}
5962

6063
func defineMacro(name string, fun primitive) {
6164
sym := intern(name)
6265
if getMacro(sym) != nil {
6366
println("*** Warning: redefining macro ", name, " -> ", getMacro(sym))
6467
}
65-
prim := LPrimitive{name, fun, "(<any>)"}
66-
defMacro(sym, &prim)
68+
prim := newPrimitive(name, fun, "(<any>)")
69+
defMacro(sym, prim)
6770
}
6871

6972
func getKeywords() []LAny {
@@ -93,31 +96,50 @@ func getGlobals() []LAny {
9396
return syms
9497
}
9598

96-
func global(sym LAny) LAny {
97-
s := sym.(*LSymbol)
98-
if s.tag >= len(globals) {
99-
return nil
99+
func globalValue(tag int) LAny {
100+
if tag < len(globals) {
101+
tmp := globals[tag]
102+
if tmp != nil {
103+
return tmp.val
104+
}
105+
}
106+
return nil
107+
}
108+
109+
//used to report errors, doesn't need to be fast
110+
func globalName(tag int) string {
111+
for k, v := range symtab {
112+
if v.tag == tag {
113+
return k
114+
}
100115
}
101-
tmp := globals[s.tag]
102-
if tmp == nil {
116+
return "?"
117+
}
118+
119+
func global(obj LAny) LAny {
120+
sym, ok := obj.(*LSymbol)
121+
if !ok || sym.tag < 0 || sym.tag >= len(globals) {
103122
return nil
104123
}
105-
return tmp.val
124+
return globalValue(sym.tag)
106125
}
107126

108127
type binding struct {
109-
sym LAny
128+
sym *LSymbol
110129
val LAny
111130
}
112131

113132
func defGlobal(sym LAny, val LAny) {
114-
s := sym.(*LSymbol)
133+
s, ok := sym.(*LSymbol)
134+
if !ok {
135+
panic("defGlobal with a non-symbol first argument")
136+
}
115137
if s.tag >= len(globals) {
116-
gLAny := make([]*binding, s.tag+100)
117-
copy(gLAny, globals)
118-
globals = gLAny
138+
glob := make([]*binding, s.tag+100)
139+
copy(glob, globals)
140+
globals = glob
119141
}
120-
b := binding{sym, val}
142+
b := binding{s, val}
121143
globals[s.tag] = &b
122144
delete(macroMap, sym)
123145
}

0 commit comments

Comments
 (0)