Showing
5 changed files
with
82 additions
and
21 deletions
TODO
0 → 100644
1 | -import io | 1 | +import io, os.path |
2 | 2 | ||
3 | from . import cparse | 3 | from . import cparse |
4 | from .cvisitors import Visitor | 4 | from .cvisitors import Visitor |
... | @@ -120,9 +120,10 @@ class CodeGenVisitor (Visitor) : | ... | @@ -120,9 +120,10 @@ class CodeGenVisitor (Visitor) : |
120 | __label = 0 | 120 | __label = 0 |
121 | __str_literal_label = 0 | 121 | __str_literal_label = 0 |
122 | 122 | ||
123 | - def __init__(self, path): | 123 | + def __init__(self, path, test=None): |
124 | Visitor.__init__(self) | 124 | Visitor.__init__(self) |
125 | self.path = path | 125 | self.path = path |
126 | + self.test = test | ||
126 | self.str_literal_str = io.StringIO() | 127 | self.str_literal_str = io.StringIO() |
127 | self.str_literal_dict = {} | 128 | self.str_literal_dict = {} |
128 | 129 | ||
... | @@ -180,17 +181,17 @@ class CodeGenVisitor (Visitor) : | ... | @@ -180,17 +181,17 @@ class CodeGenVisitor (Visitor) : |
180 | for c in chunks : | 181 | for c in chunks : |
181 | s = c.curr_str.getvalue() | 182 | s = c.curr_str.getvalue() |
182 | if s.strip() : | 183 | if s.strip() : |
183 | - outfile.write("\n###\n### code from file %r\n###\n" % c.path) | 184 | + outfile.write("\n#\n# code from file %r\n#\n" % c.path) |
184 | outfile.write(s) | 185 | outfile.write(s) |
185 | for c in chunks : | 186 | for c in chunks : |
186 | s = c.globals_str.getvalue() | 187 | s = c.globals_str.getvalue() |
187 | if s.strip() : | 188 | if s.strip() : |
188 | - outfile.write("\n###\n### globals from file %r\n###\n\n" % c.path) | 189 | + outfile.write("\n#\n# globals from file %r\n#\n\n" % c.path) |
189 | outfile.write(s) | 190 | outfile.write(s) |
190 | for c in chunks : | 191 | for c in chunks : |
191 | s = c.str_literal_str.getvalue() | 192 | s = c.str_literal_str.getvalue() |
192 | if s.strip() : | 193 | if s.strip() : |
193 | - outfile.write("\n###\n### string literals from file %r\n###\n\n" | 194 | + outfile.write("\n#\n# string literals from file %r\n#\n\n" |
194 | % c.path) | 195 | % c.path) |
195 | outfile.write(s) | 196 | outfile.write(s) |
196 | 197 | ||
... | @@ -396,6 +397,13 @@ class CodeGenVisitor (Visitor) : | ... | @@ -396,6 +397,13 @@ class CodeGenVisitor (Visitor) : |
396 | self.o(" ld %s %s" % (reg_to, reg_to), "Load array value") | 397 | self.o(" ld %s %s" % (reg_to, reg_to), "Load array value") |
397 | 398 | ||
398 | def vFunctionExpression(self, node): | 399 | def vFunctionExpression(self, node): |
400 | + if self.test and node.function.symbol.name == "TTCTEST" : | ||
401 | + call = node.arglist.nodes[0].get_str() | ||
402 | + expect = self.test[call] | ||
403 | + ret = self._accept_and_pop(node.arglist.nodes[1]) | ||
404 | + self.o(" ### %s == %s # == %s" % (ret, expect, call)) | ||
405 | + self.stack.done() | ||
406 | + return | ||
399 | self.c("FUNCTION CALL to %s() - begin" % | 407 | self.c("FUNCTION CALL to %s() - begin" % |
400 | node.function.symbol.name) | 408 | node.function.symbol.name) |
401 | self.stack.save_caller_saves() | 409 | self.stack.save_caller_saves() |
... | @@ -536,3 +544,13 @@ class CodeGenVisitor (Visitor) : | ... | @@ -536,3 +544,13 @@ class CodeGenVisitor (Visitor) : |
536 | def vAddrOf(self, node): | 544 | def vAddrOf(self, node): |
537 | node.expr.accept(self) | 545 | node.expr.accept(self) |
538 | self.o("", "(Address-of operator '&' used here)") | 546 | self.o("", "(Address-of operator '&' used here)") |
547 | + | ||
548 | +def compile (path) : | ||
549 | + tgt = os.path.splitext(path)[0] + ".bios" | ||
550 | + tgt, ["ttc", "asm", path, tgt] | ||
551 | + | ||
552 | +def cpp (args, path) : | ||
553 | + if args.test : | ||
554 | + return ["cpp", "-P", "-D", "TTC", path] | ||
555 | + else : | ||
556 | + return ["cpp", "-P", path] | ... | ... |
... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
8 | # $Id: cx86.py,v 1.3 2004/06/02 21:05:23 varmaa Exp $ | 8 | # $Id: cx86.py,v 1.3 2004/06/02 21:05:23 varmaa Exp $ |
9 | # --------------------------------------------------------------- | 9 | # --------------------------------------------------------------- |
10 | 10 | ||
11 | -import io | 11 | +import io, os.path |
12 | 12 | ||
13 | from . import cparse | 13 | from . import cparse |
14 | from .cvisitors import Visitor | 14 | from .cvisitors import Visitor |
... | @@ -405,7 +405,7 @@ class CodeGenVisitor(Visitor): | ... | @@ -405,7 +405,7 @@ class CodeGenVisitor(Visitor): |
405 | # Current label number for generating string literal labels. | 405 | # Current label number for generating string literal labels. |
406 | __str_literal_label = 0 | 406 | __str_literal_label = 0 |
407 | 407 | ||
408 | - def __init__(self, path): | 408 | + def __init__(self, path, test=None): |
409 | """Constructor. 'file' is the file object to output the | 409 | """Constructor. 'file' is the file object to output the |
410 | resulting code to.""" | 410 | resulting code to.""" |
411 | 411 | ||
... | @@ -1087,3 +1087,13 @@ class CodeGenVisitor(Visitor): | ... | @@ -1087,3 +1087,13 @@ class CodeGenVisitor(Visitor): |
1087 | # --------------------------------------------------------------- | 1087 | # --------------------------------------------------------------- |
1088 | # End of cx86.py | 1088 | # End of cx86.py |
1089 | # --------------------------------------------------------------- | 1089 | # --------------------------------------------------------------- |
1090 | + | ||
1091 | +def compile (path) : | ||
1092 | + tgt = os.path.splitext(path)[0] | ||
1093 | + return tgt, ["gcc", "-m32", "-o", tgt, path] | ||
1094 | + | ||
1095 | +def cpp (args, path) : | ||
1096 | + if args.test : | ||
1097 | + return ["cpp", "-P", "-D", "CC", path] | ||
1098 | + else : | ||
1099 | + return ["cpp", "-P", path] | ... | ... |
1 | -import argparse, sys, os.path | 1 | +import argparse, sys, os, os.path, subprocess |
2 | 2 | ||
3 | import ply.yacc as yacc | 3 | import ply.yacc as yacc |
4 | from . import cparse, cvisitors, cx86, cttc | 4 | from . import cparse, cvisitors, cx86, cttc |
... | @@ -19,9 +19,10 @@ class Compiler (object) : | ... | @@ -19,9 +19,10 @@ class Compiler (object) : |
19 | """This object encapsulates the front-end for the compiler and | 19 | """This object encapsulates the front-end for the compiler and |
20 | serves as a facade interface to the 'meat' of the compiler | 20 | serves as a facade interface to the 'meat' of the compiler |
21 | underneath.""" | 21 | underneath.""" |
22 | - def __init__ (self, arch, path) : | 22 | + def __init__ (self, arch, path, test) : |
23 | self.arch = arch | 23 | self.arch = arch |
24 | self.path = path | 24 | self.path = path |
25 | + self.test = test | ||
25 | self.total_errors = 0 | 26 | self.total_errors = 0 |
26 | self.total_warnings = 0 | 27 | self.total_warnings = 0 |
27 | def _parse (self) : | 28 | def _parse (self) : |
... | @@ -41,7 +42,7 @@ class Compiler (object) : | ... | @@ -41,7 +42,7 @@ class Compiler (object) : |
41 | self._compile_phase(cvisitors.SymtabVisitor()) | 42 | self._compile_phase(cvisitors.SymtabVisitor()) |
42 | self._compile_phase(cvisitors.TypeCheckVisitor()) | 43 | self._compile_phase(cvisitors.TypeCheckVisitor()) |
43 | self._compile_phase(cvisitors.FlowControlVisitor()) | 44 | self._compile_phase(cvisitors.FlowControlVisitor()) |
44 | - comp = self.arch.CodeGenVisitor(self.path) | 45 | + comp = self.arch.CodeGenVisitor(self.path, self.test) |
45 | self._compile_phase(comp) | 46 | self._compile_phase(comp) |
46 | if ast_file is not None: | 47 | if ast_file is not None: |
47 | self._compile_phase(cvisitors.ASTPrinterVisitor(ast_file)) | 48 | self._compile_phase(cvisitors.ASTPrinterVisitor(ast_file)) |
... | @@ -58,14 +59,14 @@ class Compiler (object) : | ... | @@ -58,14 +59,14 @@ class Compiler (object) : |
58 | try: | 59 | try: |
59 | chunk = self._do_compile(show_ast) | 60 | chunk = self._do_compile(show_ast) |
60 | except cparse.ParseError: | 61 | except cparse.ParseError: |
61 | - print("Errors encountered, bailing.") | 62 | + print("... errors encountered, bailing") |
62 | return | 63 | return |
63 | except CompileError: | 64 | except CompileError: |
64 | self._print_stats() | 65 | self._print_stats() |
65 | - print("Errors encountered, bailing.") | 66 | + print("... errors encountered, bailing") |
66 | return | 67 | return |
67 | self._print_stats() | 68 | self._print_stats() |
68 | - print("Compile successful.") | 69 | + print("... compile successful") |
69 | return chunk | 70 | return chunk |
70 | 71 | ||
71 | def main (args=None) : | 72 | def main (args=None) : |
... | @@ -77,28 +78,53 @@ def main (args=None) : | ... | @@ -77,28 +78,53 @@ def main (args=None) : |
77 | help="write output to PATH") | 78 | help="write output to PATH") |
78 | parser.add_argument("--ast", action="store_true", default=False, | 79 | parser.add_argument("--ast", action="store_true", default=False, |
79 | help="dump AST for each C file") | 80 | help="dump AST for each C file") |
80 | - parser.add_argument("--arch", action="store", choices=list(ARCH), | 81 | + parser.add_argument("--cpp", "-p", action="store_true", default=False, |
81 | - default="ttc", | 82 | + help="process input file through cpp") |
82 | - help="output assembly for specified architecture (default 'ttc')") | 83 | + parser.add_argument("--arch", action="store", choices=list(ARCH), default="ttc", |
83 | - parser.add_argument("-t", "--ttc", action="store_const", const="ttc", | 84 | + help="output assembly for specified architecture" |
84 | - dest="arch", help="output TTC assembly") | 85 | + " (default 'ttc')") |
86 | + parser.add_argument("--compile", "-c", action="store_true", default=False, | ||
87 | + help="compile generated ASM") | ||
88 | + parser.add_argument("--test", "-t", action="store_true", default=False, | ||
89 | + help="test compiler") | ||
85 | parser.add_argument("source", nargs="+", metavar="PATH", | 90 | parser.add_argument("source", nargs="+", metavar="PATH", |
86 | help="C source files(s) to compile") | 91 | help="C source files(s) to compile") |
87 | args = parser.parse_args(args) | 92 | args = parser.parse_args(args) |
88 | chunks = [] | 93 | chunks = [] |
94 | + if args.test : | ||
95 | + print("Generating tests") | ||
96 | + print("..$ gcc -o cct-test -D CC %s" % " ".join(args.source)) | ||
97 | + subprocess.run(["gcc", "-o", "cct-test", "-D", "CC"] + args.source) | ||
98 | + print("..$ cct-test") | ||
99 | + testdata = subprocess.check_output("cct-test").decode() | ||
100 | + args.test = dict(line.rsplit(" => ", 1) for line in testdata.splitlines()) | ||
89 | for src in args.source : | 101 | for src in args.source : |
90 | - print("Compiling %r" % src) | ||
91 | if args.ast : | 102 | if args.ast : |
92 | ast_path = os.path.splitext(src)[0] + ".ast" | 103 | ast_path = os.path.splitext(src)[0] + ".ast" |
93 | print("Dumping AST to %r" % ast_path) | 104 | print("Dumping AST to %r" % ast_path) |
94 | ast_file = open(ast_path, "w") | 105 | ast_file = open(ast_path, "w") |
95 | else : | 106 | else : |
96 | ast_file = None | 107 | ast_file = None |
97 | - code = "\n".join(l.rstrip() for l in open(src).readlines()) | 108 | + if args.cpp : |
98 | - ret = Compiler(ARCH[args.arch], src).compile(code, ast_file) | 109 | + print("Preprocessing %r" % src) |
110 | + cpp = ARCH[args.arch].cpp(args, src) | ||
111 | + print("..$ %s" % " ".join(cpp)) | ||
112 | + code = subprocess.check_output(cpp).decode() | ||
113 | + print("Compiling preprocessed %r (line numbers may have changed)" % src) | ||
114 | + else : | ||
115 | + code = "\n".join(l.rstrip() for l in open(src).readlines()) | ||
116 | + print("Compiling %r" % src) | ||
117 | + ret = Compiler(ARCH[args.arch], src, args.test).compile(code, ast_file) | ||
99 | if ast_file is not None : | 118 | if ast_file is not None : |
100 | ast_file.close() | 119 | ast_file.close() |
101 | if ret is None : | 120 | if ret is None : |
102 | sys.exit(1) | 121 | sys.exit(1) |
103 | chunks.append(ret) | 122 | chunks.append(ret) |
104 | ARCH[args.arch].CodeGenVisitor.concat(args.o, chunks) | 123 | ARCH[args.arch].CodeGenVisitor.concat(args.o, chunks) |
124 | + args.o.flush() | ||
125 | + if args.compile : | ||
126 | + tgt, cmd = ARCH[args.arch].compile(args.o.name) | ||
127 | + print("Building %r" % tgt) | ||
128 | + print(".. $ %s" % " ".join(cmd)) | ||
129 | + ret = subprocess.run(cmd) | ||
130 | + print("... exited with status %s" % ret.returncode) | ... | ... |
-
Please register or login to post a comment