@@ -57,6 +57,7 @@ type compiler struct {
57
57
SymTable * symtable.SymTable
58
58
scopeType compilerScopeType
59
59
qualname string
60
+ private string
60
61
parent * compiler
61
62
depth int
62
63
}
@@ -135,7 +136,7 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
135
136
valueOnStack := false
136
137
switch node := Ast .(type ) {
137
138
case * ast.Module :
138
- c .Stmts (node .Body )
139
+ c .Stmts (c . docString ( node .Body , false ) )
139
140
case * ast.Interactive :
140
141
c .Stmts (node .Body )
141
142
case * ast.Expression :
@@ -153,7 +154,41 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
153
154
case * ast.FunctionDef :
154
155
code .Name = string (node .Name )
155
156
c .setQualname () // FIXME is this in the right place!
156
- c .Stmts (c .docString (node .Body ))
157
+ c .Stmts (c .docString (node .Body , true ))
158
+ case * ast.ClassDef :
159
+ code .Name = string (node .Name )
160
+ /* load (global) __name__ ... */
161
+ c .NameOp ("__name__" , ast .Load )
162
+ /* ... and store it as __module__ */
163
+ c .NameOp ("__module__" , ast .Store )
164
+ c .setQualname () // FIXME is this in the right place!
165
+ if c .qualname == "" {
166
+ panic ("Need qualname" )
167
+ }
168
+
169
+ c .LoadConst (py .String (c .qualname ))
170
+ c .NameOp ("__qualname__" , ast .Store )
171
+
172
+ /* compile the body proper */
173
+ c .Stmts (c .docString (node .Body , false ))
174
+
175
+ if SymTable .NeedsClassClosure {
176
+ /* return the (empty) __class__ cell */
177
+ i := c .FindId ("__class__" , code .Cellvars )
178
+ if i != 0 {
179
+ panic ("__class__ must be first constant" )
180
+ }
181
+ /* Return the cell where to store __class__ */
182
+ c .OpArg (vm .LOAD_CLOSURE , uint32 (i ))
183
+ } else {
184
+ if len (code .Cellvars ) != 0 {
185
+ panic ("Can't have cellvars without closure" )
186
+ }
187
+ /* This happens when nobody references the cell. Return None. */
188
+ c .LoadConst (py .None )
189
+ }
190
+ c .Op (vm .RETURN_VALUE )
191
+
157
192
default :
158
193
panic (py .ExceptionNewf (py .SyntaxError , "Unknown ModuleBase: %v" , Ast ))
159
194
}
@@ -172,18 +207,29 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
172
207
}
173
208
174
209
// Check for docstring as first Expr in body and remove it and set the
175
- // first constant if found.
176
- func (c * compiler ) docString (body []ast.Stmt ) []ast.Stmt {
210
+ // first constant if found if fn is set, or set __doc__ if it isn't
211
+ func (c * compiler ) docString (body []ast.Stmt , fn bool ) []ast.Stmt {
212
+ var docstring * ast.Str
177
213
if len (body ) > 0 {
178
214
if expr , ok := body [0 ].(* ast.ExprStmt ); ok {
179
- if docstring , ok := expr .Value .(* ast.Str ); ok {
180
- c .Const (docstring .S )
181
- return body [1 :]
215
+ if docstring , ok = expr .Value .(* ast.Str ); ok {
216
+ body = body [1 :]
182
217
}
183
218
}
184
219
}
185
- // If no docstring put None in
186
- c .Const (py .None )
220
+ if fn {
221
+ if docstring != nil {
222
+ c .Const (docstring .S )
223
+ } else {
224
+ // If no docstring put None in
225
+ c .Const (py .None )
226
+ }
227
+ } else {
228
+ if docstring != nil {
229
+ c .LoadConst (docstring .S )
230
+ c .NameOp ("__doc__" , ast .Store )
231
+ }
232
+ }
187
233
return body
188
234
}
189
235
@@ -297,9 +343,8 @@ func (c *compiler) getRefType(name string) symtable.Scope {
297
343
}
298
344
299
345
// makeClosure constructs the function or closure for a func/class/lambda etc
300
- func (c * compiler ) makeClosure (code * py.Code , args uint32 , child * compiler ) {
346
+ func (c * compiler ) makeClosure (code * py.Code , args uint32 , child * compiler , qualname string ) {
301
347
free := uint32 (len (code .Freevars ))
302
- qualname := child .qualname
303
348
if qualname == "" {
304
349
qualname = c .qualname
305
350
}
@@ -407,12 +452,12 @@ func (c *compiler) setQualname() {
407
452
}
408
453
409
454
// Compile a function
410
- func (c * compiler ) compileFunc (Ast ast.Ast , Args * ast.Arguments , DecoratorList []ast.Expr , Returns ast.Expr ) {
455
+ func (c * compiler ) compileFunc (compilerScope compilerScopeType , Ast ast.Ast , Args * ast.Arguments , DecoratorList []ast.Expr , Returns ast.Expr ) {
411
456
newSymTable := c .SymTable .FindChild (Ast )
412
457
if newSymTable == nil {
413
458
panic ("No symtable found for function" )
414
459
}
415
- newC := newCompiler (c , compilerScopeFunction )
460
+ newC := newCompiler (c , compilerScope )
416
461
code , err := newC .compileAst (Ast , c .Code .Filename , 0 , false , newSymTable )
417
462
if err != nil {
418
463
panic (err )
@@ -468,14 +513,67 @@ func (c *compiler) compileFunc(Ast ast.Ast, Args *ast.Arguments, DecoratorList [
468
513
posdefaults := uint32 (len (Args .Defaults ))
469
514
kwdefaults := uint32 (len (Args .KwDefaults ))
470
515
args := uint32 (posdefaults + (kwdefaults << 8 ) + (num_annotations << 16 ))
471
- c .makeClosure (code , args , newC )
516
+ c .makeClosure (code , args , newC , newC . qualname )
472
517
473
518
// Call decorators
474
519
for _ = range DecoratorList {
475
520
c .OpArg (vm .CALL_FUNCTION , 1 ) // 1 positional, 0 keyword pair
476
521
}
477
522
}
478
523
524
+ // Compile class definition
525
+ func (c * compiler ) class (Ast ast.Ast , class * ast.ClassDef ) {
526
+ // Load decorators onto stack
527
+ for _ , expr := range class .DecoratorList {
528
+ c .Expr (expr )
529
+ }
530
+
531
+ /* ultimately generate code for:
532
+ <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
533
+ where:
534
+ <func> is a function/closure created from the class body;
535
+ it has a single argument (__locals__) where the dict
536
+ (or MutableSequence) representing the locals is passed
537
+ <name> is the class name
538
+ <bases> is the positional arguments and *varargs argument
539
+ <keywords> is the keyword arguments and **kwds argument
540
+ This borrows from compiler_call.
541
+ */
542
+
543
+ /* 1. compile the class body into a code object */
544
+ newSymTable := c .SymTable .FindChild (Ast )
545
+ if newSymTable == nil {
546
+ panic ("No symtable found for class" )
547
+ }
548
+ newC := newCompiler (c , compilerScopeClass )
549
+ /* use the class name for name mangling */
550
+ newC .private = string (class .Name )
551
+ code , err := newC .compileAst (Ast , c .Code .Filename , 0 , false , newSymTable )
552
+ if err != nil {
553
+ panic (err )
554
+ }
555
+
556
+ /* 2. load the 'build_class' function */
557
+ c .Op (vm .LOAD_BUILD_CLASS )
558
+
559
+ /* 3. load a function (or closure) made from the code object */
560
+ c .makeClosure (code , 0 , newC , string (class .Name ))
561
+
562
+ /* 4. load class name */
563
+ c .LoadConst (py .String (class .Name ))
564
+
565
+ /* 5. generate the rest of the code for the call */
566
+ c .callHelper (2 , class .Bases , class .Keywords , class .Starargs , class .Kwargs )
567
+
568
+ /* 6. apply decorators */
569
+ for _ = range class .DecoratorList {
570
+ c .OpArg (vm .CALL_FUNCTION , 1 ) // 1 positional, 0 keyword pair
571
+ }
572
+
573
+ /* 7. store into <name> */
574
+ c .NameOp (string (class .Name ), ast .Store )
575
+ }
576
+
479
577
// Compile statement
480
578
func (c * compiler ) Stmt (stmt ast.Stmt ) {
481
579
switch node := stmt .(type ) {
@@ -485,7 +583,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
485
583
// Body []Stmt
486
584
// DecoratorList []Expr
487
585
// Returns Expr
488
- c .compileFunc (stmt , node .Args , node .DecoratorList , node .Returns )
586
+ c .compileFunc (compilerScopeFunction , stmt , node .Args , node .DecoratorList , node .Returns )
489
587
c .NameOp (string (node .Name ), ast .Store )
490
588
491
589
case * ast.ClassDef :
@@ -496,7 +594,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
496
594
// Kwargs Expr
497
595
// Body []Stmt
498
596
// DecoratorList []Expr
499
- panic ( "FIXME compile: ClassDef not implemented" )
597
+ c . class ( stmt , node )
500
598
case * ast.Return :
501
599
// Value Expr
502
600
if node .Value != nil {
@@ -752,6 +850,8 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
752
850
}
753
851
case symtable .ScopeGlobalExplicit :
754
852
optype = OP_GLOBAL
853
+ case symtable .ScopeInvalid :
854
+ // scope can be unset
755
855
default :
756
856
panic (fmt .Sprintf ("NameOp: Invalid scope %v for %q" , scope , mangled ))
757
857
}
@@ -833,6 +933,34 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
833
933
c .OpArg (op , c .Index (mangled , dict ))
834
934
}
835
935
936
+ // Call a function which is already on the stack with n arguments already on the stack
937
+ func (c * compiler ) callHelper (n int , Args []ast.Expr , Keywords []* ast.Keyword , Starargs ast.Expr , Kwargs ast.Expr ) {
938
+ args := len (Args ) + n
939
+ for i := range Args {
940
+ c .Expr (Args [i ])
941
+ }
942
+ kwargs := len (Keywords )
943
+ for i := range Keywords {
944
+ kw := Keywords [i ]
945
+ c .LoadConst (py .String (kw .Arg ))
946
+ c .Expr (kw .Value )
947
+ }
948
+ op := byte (vm .CALL_FUNCTION )
949
+ if Starargs != nil {
950
+ c .Expr (Starargs )
951
+ if Kwargs != nil {
952
+ c .Expr (Kwargs )
953
+ op = vm .CALL_FUNCTION_VAR_KW
954
+ } else {
955
+ op = vm .CALL_FUNCTION_VAR
956
+ }
957
+ } else if Kwargs != nil {
958
+ c .Expr (Kwargs )
959
+ op = vm .CALL_FUNCTION_KW
960
+ }
961
+ c .OpArg (op , uint32 (args + kwargs << 8 ))
962
+ }
963
+
836
964
// Compile expressions
837
965
func (c * compiler ) Expr (expr ast.Expr ) {
838
966
switch node := expr .(type ) {
@@ -914,7 +1042,7 @@ func (c *compiler) Expr(expr ast.Expr) {
914
1042
// Args *Arguments
915
1043
// Body Expr
916
1044
// newC := Compiler
917
- c .compileFunc (expr , node .Args , nil , nil )
1045
+ c .compileFunc (compilerScopeLambda , expr , node .Args , nil , nil )
918
1046
case * ast.IfExp :
919
1047
// Test Expr
920
1048
// Body Expr
@@ -1035,30 +1163,7 @@ func (c *compiler) Expr(expr ast.Expr) {
1035
1163
// Starargs Expr
1036
1164
// Kwargs Expr
1037
1165
c .Expr (node .Func )
1038
- args := len (node .Args )
1039
- for i := range node .Args {
1040
- c .Expr (node .Args [i ])
1041
- }
1042
- kwargs := len (node .Keywords )
1043
- for i := range node .Keywords {
1044
- kw := node .Keywords [i ]
1045
- c .LoadConst (py .String (kw .Arg ))
1046
- c .Expr (kw .Value )
1047
- }
1048
- op := byte (vm .CALL_FUNCTION )
1049
- if node .Starargs != nil {
1050
- c .Expr (node .Starargs )
1051
- if node .Kwargs != nil {
1052
- c .Expr (node .Kwargs )
1053
- op = vm .CALL_FUNCTION_VAR_KW
1054
- } else {
1055
- op = vm .CALL_FUNCTION_VAR
1056
- }
1057
- } else if node .Kwargs != nil {
1058
- c .Expr (node .Kwargs )
1059
- op = vm .CALL_FUNCTION_KW
1060
- }
1061
- c .OpArg (op , uint32 (args + kwargs << 8 ))
1166
+ c .callHelper (0 , node .Args , node .Keywords , node .Starargs , node .Kwargs )
1062
1167
case * ast.Num :
1063
1168
// N Object
1064
1169
c .LoadConst (node .N )
0 commit comments