|
1 | 1 | // compile python code |
2 | | -// |
3 | | -// Need to port the 10,000 lines of compiling machinery, into a |
4 | | -// different module probably. |
5 | | -// |
6 | | -// In the mean time, cheat horrendously by calling python3.4 to do our |
7 | | -// dirty work under the hood! |
8 | 2 |
|
9 | 3 | package compile |
10 | 4 |
|
11 | 5 | import ( |
12 | | - "bytes" |
13 | 6 | "fmt" |
14 | | - "os" |
15 | | - "os/exec" |
16 | | - "strings" |
17 | 7 |
|
18 | 8 | "github.com/ncw/gpython/ast" |
19 | | - "github.com/ncw/gpython/marshal" |
20 | 9 | "github.com/ncw/gpython/parser" |
21 | 10 | "github.com/ncw/gpython/py" |
22 | 11 | "github.com/ncw/gpython/symtable" |
23 | 12 | "github.com/ncw/gpython/vm" |
24 | 13 | ) |
25 | 14 |
|
26 | | -// Set in py to avoid circular import |
27 | | -func init() { |
28 | | - py.Compile = Compile |
| 15 | +// Loop |
| 16 | +type loop struct { |
| 17 | + Start *Label |
| 18 | + End *Label |
| 19 | + IsForLoop bool |
29 | 20 | } |
30 | 21 |
|
31 | | -// Compile(source, filename, mode, flags, dont_inherit) -> code object |
32 | | -// |
33 | | -// Compile the source string (a Python module, statement or expression) |
34 | | -// into a code object that can be executed by exec() or eval(). |
35 | | -// The filename will be used for run-time error messages. |
36 | | -// The mode must be 'exec' to compile a module, 'single' to compile a |
37 | | -// single (interactive) statement, or 'eval' to compile an expression. |
38 | | -// The flags argument, if present, controls which future statements influence |
39 | | -// the compilation of the code. |
40 | | -// The dont_inherit argument, if non-zero, stops the compilation inheriting |
41 | | -// the effects of any future statements in effect in the code calling |
42 | | -// compile; if absent or zero these statements do influence the compilation, |
43 | | -// in addition to any features explicitly specified. |
44 | | -func LegacyCompile(str, filename, mode string, flags int, dont_inherit bool) py.Object { |
45 | | - dont_inherit_str := "False" |
46 | | - if dont_inherit { |
47 | | - dont_inherit_str = "True" |
48 | | - } |
49 | | - // FIXME escaping in filename |
50 | | - code := fmt.Sprintf(`import sys, marshal |
51 | | -str = sys.stdin.buffer.read().decode("utf-8") |
52 | | -code = compile(str, "%s", "%s", %d, %s) |
53 | | -marshalled_code = marshal.dumps(code) |
54 | | -sys.stdout.buffer.write(marshalled_code) |
55 | | -sys.stdout.close()`, |
56 | | - filename, |
57 | | - mode, |
58 | | - flags, |
59 | | - dont_inherit_str, |
60 | | - ) |
61 | | - cmd := exec.Command("python3.4", "-c", code) |
62 | | - cmd.Stdin = strings.NewReader(str) |
63 | | - var out bytes.Buffer |
64 | | - cmd.Stdout = &out |
65 | | - var stderr bytes.Buffer |
66 | | - cmd.Stderr = &stderr |
67 | | - err := cmd.Run() |
68 | | - if err != nil { |
69 | | - fmt.Fprintf(os.Stderr, "--- Failed to run python3.4 compile ---\n") |
70 | | - fmt.Fprintf(os.Stderr, "--------------------\n") |
71 | | - os.Stderr.Write(stderr.Bytes()) |
72 | | - fmt.Fprintf(os.Stderr, "--------------------\n") |
73 | | - panic(err) |
74 | | - } |
75 | | - obj, err := marshal.ReadObject(bytes.NewBuffer(out.Bytes())) |
76 | | - if err != nil { |
77 | | - panic(err) |
| 22 | +// Loopstack |
| 23 | +type loopstack []loop |
| 24 | + |
| 25 | +// Push a loop |
| 26 | +func (ls *loopstack) Push(l loop) { |
| 27 | + *ls = append(*ls, l) |
| 28 | +} |
| 29 | + |
| 30 | +// Pop a loop |
| 31 | +func (ls *loopstack) Pop() { |
| 32 | + *ls = (*ls)[:len(*ls)-1] |
| 33 | +} |
| 34 | + |
| 35 | +// Return current loop or nil for none |
| 36 | +func (ls loopstack) Top() *loop { |
| 37 | + if len(ls) == 0 { |
| 38 | + return nil |
78 | 39 | } |
79 | | - return obj |
| 40 | + return &ls[len(ls)-1] |
| 41 | +} |
| 42 | + |
| 43 | +// State for the compiler |
| 44 | +type compiler struct { |
| 45 | + Code *py.Code // code being built up |
| 46 | + OpCodes Instructions |
| 47 | + loops loopstack |
| 48 | + SymTable *symtable.SymTable |
| 49 | +} |
| 50 | + |
| 51 | +// Set in py to avoid circular import |
| 52 | +func init() { |
| 53 | + py.Compile = Compile |
80 | 54 | } |
81 | 55 |
|
82 | 56 | // Compile(source, filename, mode, flags, dont_inherit) -> code object |
@@ -159,42 +133,6 @@ func CompileAst(Ast ast.Ast, filename string, flags int, dont_inherit bool, SymT |
159 | 133 | return code, nil |
160 | 134 | } |
161 | 135 |
|
162 | | -// Loop |
163 | | -type loop struct { |
164 | | - Start *Label |
165 | | - End *Label |
166 | | - IsForLoop bool |
167 | | -} |
168 | | - |
169 | | -// Loopstack |
170 | | -type loopstack []loop |
171 | | - |
172 | | -// Push a loop |
173 | | -func (ls *loopstack) Push(l loop) { |
174 | | - *ls = append(*ls, l) |
175 | | -} |
176 | | - |
177 | | -// Pop a loop |
178 | | -func (ls *loopstack) Pop() { |
179 | | - *ls = (*ls)[:len(*ls)-1] |
180 | | -} |
181 | | - |
182 | | -// Return current loop or nil for none |
183 | | -func (ls loopstack) Top() *loop { |
184 | | - if len(ls) == 0 { |
185 | | - return nil |
186 | | - } |
187 | | - return &ls[len(ls)-1] |
188 | | -} |
189 | | - |
190 | | -// State for the compiler |
191 | | -type compiler struct { |
192 | | - Code *py.Code // code being built up |
193 | | - OpCodes Instructions |
194 | | - loops loopstack |
195 | | - SymTable *symtable.SymTable |
196 | | -} |
197 | | - |
198 | 136 | // Check for docstring as first Expr in body and remove it and set the |
199 | 137 | // first constant if found. |
200 | 138 | func (c *compiler) docString(body []ast.Stmt) []ast.Stmt { |
|
0 commit comments