Skip to content

Commit 9402ed8

Browse files
committed
compile: improve coverage and tidy code
1 parent 08f7c83 commit 9402ed8

File tree

4 files changed

+347
-77
lines changed

4 files changed

+347
-77
lines changed

compile/compile.go

+98-77
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// compile python code
22
package compile
33

4+
// FIXME line numbers
5+
// FIXME name mangling
46
// FIXME kill ast.Identifier and turn into string?
57

68
import (
@@ -64,15 +66,16 @@ const (
6466

6567
// State for the compiler
6668
type compiler struct {
67-
Code *py.Code // code being built up
68-
OpCodes Instructions
69-
loops loopstack
70-
SymTable *symtable.SymTable
71-
scopeType compilerScopeType
72-
qualname string
73-
private string
74-
parent *compiler
75-
depth int
69+
Code *py.Code // code being built up
70+
OpCodes Instructions
71+
loops loopstack
72+
SymTable *symtable.SymTable
73+
scopeType compilerScopeType
74+
qualname string
75+
private string
76+
parent *compiler
77+
depth int
78+
interactive bool
7679
}
7780

7881
// Set in py to avoid circular import
@@ -105,76 +108,103 @@ func Compile(str, filename, mode string, futureFlags int, dont_inherit bool) (py
105108
return nil, err
106109
}
107110
c := newCompiler(nil, compilerScopeModule)
108-
return c.compileAst(Ast, filename, futureFlags, dont_inherit, SymTable)
111+
err = c.compileAst(Ast, filename, futureFlags, dont_inherit, SymTable)
112+
if err != nil {
113+
return nil, err
114+
}
115+
return c.Code, nil
109116
}
110117

111-
// Make a new compiler
118+
// Make a new compiler object with empty code object
112119
func newCompiler(parent *compiler, scopeType compilerScopeType) *compiler {
120+
code := &py.Code{
121+
Firstlineno: 1, // FIXME
122+
Name: "<module>", // FIXME
123+
}
113124
c := &compiler{
114-
// Code: code,
115-
// SymTable: SymTable,
116-
parent: parent,
117-
scopeType: scopeType,
118-
depth: 1,
125+
Code: code,
126+
parent: parent,
127+
scopeType: scopeType,
128+
depth: 1,
129+
interactive: false,
119130
}
120131
if parent != nil {
121132
c.depth = parent.depth + 1
122133
}
123134
return c
124135
}
125136

126-
// As Compile but takes an Ast
127-
func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, dont_inherit bool, SymTable *symtable.SymTable) (code *py.Code, err error) {
137+
// Create a new compiler object at Ast, using private for name mangling
138+
func (c *compiler) newCompilerScope(compilerScope compilerScopeType, Ast ast.Ast, private string) (newC *compiler) {
139+
newSymTable := c.SymTable.FindChild(Ast)
140+
if newSymTable == nil {
141+
panic(fmt.Sprintf("No symtable found for scope type %v", compilerScope))
142+
}
143+
144+
newC = newCompiler(c, compilerScope)
145+
146+
/* use the class name for name mangling */
147+
newC.private = private
148+
149+
if newSymTable.NeedsClassClosure {
150+
// Cook up a implicit __class__ cell.
151+
if compilerScope != compilerScopeClass {
152+
panic("class closure not in class")
153+
}
154+
newSymTable.Symbols["__class__"] = symtable.Symbol{Scope: symtable.ScopeCell}
155+
}
156+
157+
err := newC.compileAst(Ast, c.Code.Filename, 0, false, newSymTable)
158+
if err != nil {
159+
panic(err)
160+
}
161+
return newC
162+
}
163+
164+
// Compile an Ast with the current compiler
165+
func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, dont_inherit bool, SymTable *symtable.SymTable) (err error) {
128166
defer func() {
129167
if r := recover(); r != nil {
130168
err = py.MakeException(r)
131169
}
132170
}()
133-
//fmt.Println(ast.Dump(Ast))
134-
code = &py.Code{
135-
Filename: filename,
136-
Firstlineno: 1, // FIXME
137-
Name: "<module>", // FIXME
138-
// Argcount: int32(len(node.Args.Args)),
139-
// Name: string(node.Name),
140-
// Kwonlyargcount: int32(len(node.Args.Kwonlyargs)),
141-
// Nlocals: int32(len(SymTable.Varnames)),
142-
}
143-
c.Code = code
144171
c.SymTable = SymTable
172+
code := c.Code
173+
code.Filename = filename
145174
code.Varnames = append(code.Varnames, SymTable.Varnames...)
146-
code.Cellvars = SymTable.Find(symtable.ScopeCell, 0)
147-
code.Freevars = SymTable.Find(symtable.ScopeFree, symtable.DefFreeClass)
175+
code.Cellvars = append(code.Cellvars, SymTable.Find(symtable.ScopeCell, 0)...)
176+
code.Freevars = append(code.Freevars, SymTable.Find(symtable.ScopeFree, symtable.DefFreeClass)...)
148177
code.Flags = c.codeFlags(SymTable) | int32(futureFlags&py.CO_COMPILER_FLAGS_MASK)
149178
valueOnStack := false
150179
switch node := Ast.(type) {
151180
case *ast.Module:
152181
c.Stmts(c.docString(node.Body, false))
153182
case *ast.Interactive:
183+
c.interactive = true
154184
c.Stmts(node.Body)
155185
case *ast.Expression:
156186
c.Expr(node.Body)
157187
valueOnStack = true
158188
case *ast.Suite:
159-
c.Stmts(node.Body)
189+
panic("suite should not be possible")
160190
case *ast.Lambda:
161191
// Make None the first constant as lambda can't have a docstring
162192
c.Const(py.None)
163193
code.Name = "<lambda>"
164-
c.setQualname() // FIXME is this in the right place!
194+
c.setQualname()
165195
c.Expr(node.Body)
166196
valueOnStack = true
167197
case *ast.FunctionDef:
168198
code.Name = string(node.Name)
169-
c.setQualname() // FIXME is this in the right place!
199+
c.setQualname()
170200
c.Stmts(c.docString(node.Body, true))
171201
case *ast.ClassDef:
172202
code.Name = string(node.Name)
173203
/* load (global) __name__ ... */
174204
c.NameOp("__name__", ast.Load)
175205
/* ... and store it as __module__ */
176206
c.NameOp("__module__", ast.Store)
177-
c.setQualname() // FIXME is this in the right place!
207+
c.setQualname()
178208
if c.qualname == "" {
179209
panic("Need qualname")
180210
}
@@ -230,7 +260,7 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
230260
c.comprehensionGenerator(node.Generators, 0, node.Elt, nil, Ast)
231261

232262
default:
233-
panic(py.ExceptionNewf(py.SyntaxError, "Unknown ModuleBase: %v", Ast))
263+
panic(fmt.Sprintf("Unknown ModuleBase: %v", Ast))
234264
}
235265
if !c.OpCodes.EndsWithReturn() {
236266
// add a return
@@ -243,7 +273,7 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
243273
code.Code = c.OpCodes.Assemble()
244274
code.Stacksize = int32(c.OpCodes.StackDepth())
245275
code.Nlocals = int32(len(code.Varnames))
246-
return code, nil
276+
return nil
247277
}
248278

249279
// Check for docstring as first Expr in body and remove it and set the
@@ -385,9 +415,6 @@ func (c *compiler) getRefType(name string) symtable.Scope {
385415
// makeClosure constructs the function or closure for a func/class/lambda etc
386416
func (c *compiler) makeClosure(code *py.Code, args uint32, child *compiler, qualname string) {
387417
free := uint32(len(code.Freevars))
388-
if qualname == "" {
389-
qualname = c.qualname
390-
}
391418

392419
if free == 0 {
393420
c.LoadConst(code)
@@ -493,18 +520,9 @@ func (c *compiler) setQualname() {
493520

494521
// Compile a function
495522
func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Args *ast.Arguments, DecoratorList []ast.Expr, Returns ast.Expr) {
496-
newSymTable := c.SymTable.FindChild(Ast)
497-
if newSymTable == nil {
498-
panic("No symtable found for function")
499-
}
500-
newC := newCompiler(c, compilerScope)
501-
code, err := newC.compileAst(Ast, c.Code.Filename, 0, false, newSymTable)
502-
if err != nil {
503-
panic(err)
504-
}
505-
// FIXME need these set in code before we compile - (pass in node?)
506-
code.Argcount = int32(len(Args.Args))
507-
code.Kwonlyargcount = int32(len(Args.Kwonlyargs))
523+
newC := c.newCompilerScope(compilerScope, Ast, "")
524+
newC.Code.Argcount = int32(len(Args.Args))
525+
newC.Code.Kwonlyargcount = int32(len(Args.Kwonlyargs))
508526

509527
// Defaults
510528
c.Exprs(Args.Defaults)
@@ -549,7 +567,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
549567
posdefaults := uint32(len(Args.Defaults))
550568
kwdefaults := uint32(len(Args.KwDefaults))
551569
args := uint32(posdefaults + (kwdefaults << 8) + (num_annotations << 16))
552-
c.makeClosure(code, args, newC, newC.qualname)
570+
c.makeClosure(newC.Code, args, newC, newC.qualname)
553571

554572
// Call decorators
555573
for _ = range DecoratorList {
@@ -575,23 +593,24 @@ func (c *compiler) class(Ast ast.Ast, class *ast.ClassDef) {
575593
*/
576594

577595
/* 1. compile the class body into a code object */
578-
newSymTable := c.SymTable.FindChild(Ast)
579-
if newSymTable == nil {
580-
panic("No symtable found for class")
581-
}
582-
newC := newCompiler(c, compilerScopeClass)
596+
newC := c.newCompilerScope(compilerScopeClass, Ast, string(class.Name))
597+
// newSymTable := c.SymTable.FindChild(Ast)
598+
// if newSymTable == nil {
599+
// panic("No symtable found for class")
600+
// }
601+
// newC := newCompiler(c, compilerScopeClass)
583602
/* use the class name for name mangling */
584603
newC.private = string(class.Name)
585-
code, err := newC.compileAst(Ast, c.Code.Filename, 0, false, newSymTable)
586-
if err != nil {
587-
panic(err)
588-
}
604+
// code, err := newC.compileAst(Ast, c.Code.Filename, 0, false, newSymTable)
605+
// if err != nil {
606+
// panic(err)
607+
// }
589608

590609
/* 2. load the 'build_class' function */
591610
c.Op(vm.LOAD_BUILD_CLASS)
592611

593612
/* 3. load a function (or closure) made from the code object */
594-
c.makeClosure(code, 0, newC, string(class.Name))
613+
c.makeClosure(newC.Code, 0, newC, string(class.Name))
595614

596615
/* 4. load class name */
597616
c.LoadConst(py.String(class.Name))
@@ -1118,8 +1137,18 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
11181137
// Implemented by symtable
11191138
case *ast.ExprStmt:
11201139
// Value Expr
1121-
c.Expr(node.Value)
1122-
c.Op(vm.POP_TOP)
1140+
if c.interactive && c.depth <= 1 {
1141+
c.Expr(node.Value)
1142+
c.Op(vm.PRINT_EXPR)
1143+
} else {
1144+
switch node.Value.(type) {
1145+
case *ast.Str:
1146+
case *ast.Num:
1147+
default:
1148+
c.Expr(node.Value)
1149+
c.Op(vm.POP_TOP)
1150+
}
1151+
}
11231152
case *ast.Pass:
11241153
// Do nothing
11251154
case *ast.Break:
@@ -1160,7 +1189,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
11601189
panic("unknown loop type")
11611190
}
11621191
default:
1163-
panic(py.ExceptionNewf(py.SyntaxError, "Unknown StmtBase: %v", stmt))
1192+
panic(fmt.Sprintf("Unknown StmtBase: %v", stmt))
11641193
}
11651194
}
11661195

@@ -1384,16 +1413,8 @@ func (c *compiler) comprehensionGenerator(generators []ast.Comprehension, gen_in
13841413

13851414
// Compile a comprehension
13861415
func (c *compiler) comprehension(expr ast.Expr, generators []ast.Comprehension) {
1387-
newSymTable := c.SymTable.FindChild(expr)
1388-
if newSymTable == nil {
1389-
panic("No symtable found for comprehension")
1390-
}
1391-
newC := newCompiler(c, compilerScopeComprehension)
1392-
code, err := newC.compileAst(expr, c.Code.Filename, 0, false, newSymTable)
1393-
if err != nil {
1394-
panic(err)
1395-
}
1396-
c.makeClosure(code, 0, newC, newC.Code.Name)
1416+
newC := c.newCompilerScope(compilerScopeComprehension, expr, "")
1417+
c.makeClosure(newC.Code, 0, newC, newC.Code.Name)
13971418
outermost_iter := generators[0].Iter
13981419
c.Expr(outermost_iter)
13991420
c.Op(vm.GET_ITER)
@@ -1825,6 +1846,6 @@ func (c *compiler) Expr(expr ast.Expr) {
18251846
// Ctx ExprContext
18261847
c.tupleOrList(vm.BUILD_TUPLE, node.Ctx, node.Elts)
18271848
default:
1828-
panic(py.ExceptionNewf(py.SyntaxError, "Unknown ExprBase: %v", expr))
1849+
panic(fmt.Sprintf("Unknown ExprBase: %v", expr))
18291850
}
18301851
}

0 commit comments

Comments
 (0)