Franck Pommereau

added test options

......@@ -8,3 +8,4 @@ __pycache__
.#*
#*
cctlib/parser.out
cct-test
......
* cparse.py: add lineno to nodes
* cttc.py & cx86.py: output lineno as comments
* make a cleaner parser
* use preprocessor
* make stdlib
* load extern symbols from stdlib (declared in .h)
import io
import io, os.path
from . import cparse
from .cvisitors import Visitor
......@@ -120,9 +120,10 @@ class CodeGenVisitor (Visitor) :
__label = 0
__str_literal_label = 0
def __init__(self, path):
def __init__(self, path, test=None):
Visitor.__init__(self)
self.path = path
self.test = test
self.str_literal_str = io.StringIO()
self.str_literal_dict = {}
......@@ -180,17 +181,17 @@ class CodeGenVisitor (Visitor) :
for c in chunks :
s = c.curr_str.getvalue()
if s.strip() :
outfile.write("\n###\n### code from file %r\n###\n" % c.path)
outfile.write("\n#\n# code from file %r\n#\n" % c.path)
outfile.write(s)
for c in chunks :
s = c.globals_str.getvalue()
if s.strip() :
outfile.write("\n###\n### globals from file %r\n###\n\n" % c.path)
outfile.write("\n#\n# globals from file %r\n#\n\n" % c.path)
outfile.write(s)
for c in chunks :
s = c.str_literal_str.getvalue()
if s.strip() :
outfile.write("\n###\n### string literals from file %r\n###\n\n"
outfile.write("\n#\n# string literals from file %r\n#\n\n"
% c.path)
outfile.write(s)
......@@ -396,6 +397,13 @@ class CodeGenVisitor (Visitor) :
self.o(" ld %s %s" % (reg_to, reg_to), "Load array value")
def vFunctionExpression(self, node):
if self.test and node.function.symbol.name == "TTCTEST" :
call = node.arglist.nodes[0].get_str()
expect = self.test[call]
ret = self._accept_and_pop(node.arglist.nodes[1])
self.o(" ### %s == %s # == %s" % (ret, expect, call))
self.stack.done()
return
self.c("FUNCTION CALL to %s() - begin" %
node.function.symbol.name)
self.stack.save_caller_saves()
......@@ -536,3 +544,13 @@ class CodeGenVisitor (Visitor) :
def vAddrOf(self, node):
node.expr.accept(self)
self.o("", "(Address-of operator '&' used here)")
def compile (path) :
tgt = os.path.splitext(path)[0] + ".bios"
tgt, ["ttc", "asm", path, tgt]
def cpp (args, path) :
if args.test :
return ["cpp", "-P", "-D", "TTC", path]
else :
return ["cpp", "-P", path]
......
......@@ -8,7 +8,7 @@
# $Id: cx86.py,v 1.3 2004/06/02 21:05:23 varmaa Exp $
# ---------------------------------------------------------------
import io
import io, os.path
from . import cparse
from .cvisitors import Visitor
......@@ -405,7 +405,7 @@ class CodeGenVisitor(Visitor):
# Current label number for generating string literal labels.
__str_literal_label = 0
def __init__(self, path):
def __init__(self, path, test=None):
"""Constructor. 'file' is the file object to output the
resulting code to."""
......@@ -1087,3 +1087,13 @@ class CodeGenVisitor(Visitor):
# ---------------------------------------------------------------
# End of cx86.py
# ---------------------------------------------------------------
def compile (path) :
tgt = os.path.splitext(path)[0]
return tgt, ["gcc", "-m32", "-o", tgt, path]
def cpp (args, path) :
if args.test :
return ["cpp", "-P", "-D", "CC", path]
else :
return ["cpp", "-P", path]
......
import argparse, sys, os.path
import argparse, sys, os, os.path, subprocess
import ply.yacc as yacc
from . import cparse, cvisitors, cx86, cttc
......@@ -19,9 +19,10 @@ class Compiler (object) :
"""This object encapsulates the front-end for the compiler and
serves as a facade interface to the 'meat' of the compiler
underneath."""
def __init__ (self, arch, path) :
def __init__ (self, arch, path, test) :
self.arch = arch
self.path = path
self.test = test
self.total_errors = 0
self.total_warnings = 0
def _parse (self) :
......@@ -41,7 +42,7 @@ class Compiler (object) :
self._compile_phase(cvisitors.SymtabVisitor())
self._compile_phase(cvisitors.TypeCheckVisitor())
self._compile_phase(cvisitors.FlowControlVisitor())
comp = self.arch.CodeGenVisitor(self.path)
comp = self.arch.CodeGenVisitor(self.path, self.test)
self._compile_phase(comp)
if ast_file is not None:
self._compile_phase(cvisitors.ASTPrinterVisitor(ast_file))
......@@ -58,14 +59,14 @@ class Compiler (object) :
try:
chunk = self._do_compile(show_ast)
except cparse.ParseError:
print("Errors encountered, bailing.")
print("... errors encountered, bailing")
return
except CompileError:
self._print_stats()
print("Errors encountered, bailing.")
print("... errors encountered, bailing")
return
self._print_stats()
print("Compile successful.")
print("... compile successful")
return chunk
def main (args=None) :
......@@ -77,28 +78,53 @@ def main (args=None) :
help="write output to PATH")
parser.add_argument("--ast", action="store_true", default=False,
help="dump AST for each C file")
parser.add_argument("--arch", action="store", choices=list(ARCH),
default="ttc",
help="output assembly for specified architecture (default 'ttc')")
parser.add_argument("-t", "--ttc", action="store_const", const="ttc",
dest="arch", help="output TTC assembly")
parser.add_argument("--cpp", "-p", action="store_true", default=False,
help="process input file through cpp")
parser.add_argument("--arch", action="store", choices=list(ARCH), default="ttc",
help="output assembly for specified architecture"
" (default 'ttc')")
parser.add_argument("--compile", "-c", action="store_true", default=False,
help="compile generated ASM")
parser.add_argument("--test", "-t", action="store_true", default=False,
help="test compiler")
parser.add_argument("source", nargs="+", metavar="PATH",
help="C source files(s) to compile")
args = parser.parse_args(args)
chunks = []
if args.test :
print("Generating tests")
print("..$ gcc -o cct-test -D CC %s" % " ".join(args.source))
subprocess.run(["gcc", "-o", "cct-test", "-D", "CC"] + args.source)
print("..$ cct-test")
testdata = subprocess.check_output("cct-test").decode()
args.test = dict(line.rsplit(" => ", 1) for line in testdata.splitlines())
for src in args.source :
print("Compiling %r" % src)
if args.ast :
ast_path = os.path.splitext(src)[0] + ".ast"
print("Dumping AST to %r" % ast_path)
ast_file = open(ast_path, "w")
else :
ast_file = None
code = "\n".join(l.rstrip() for l in open(src).readlines())
ret = Compiler(ARCH[args.arch], src).compile(code, ast_file)
if args.cpp :
print("Preprocessing %r" % src)
cpp = ARCH[args.arch].cpp(args, src)
print("..$ %s" % " ".join(cpp))
code = subprocess.check_output(cpp).decode()
print("Compiling preprocessed %r (line numbers may have changed)" % src)
else :
code = "\n".join(l.rstrip() for l in open(src).readlines())
print("Compiling %r" % src)
ret = Compiler(ARCH[args.arch], src, args.test).compile(code, ast_file)
if ast_file is not None :
ast_file.close()
if ret is None :
sys.exit(1)
chunks.append(ret)
ARCH[args.arch].CodeGenVisitor.concat(args.o, chunks)
args.o.flush()
if args.compile :
tgt, cmd = ARCH[args.arch].compile(args.o.name)
print("Building %r" % tgt)
print(".. $ %s" % " ".join(cmd))
ret = subprocess.run(cmd)
print("... exited with status %s" % ret.returncode)
......