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

Lines changed: 98 additions & 77 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy