Franck Pommereau

added cli compiler

File mode changed
import argparse, io, pkgutil, ast, types, importlib
import zinc, zinc.compil, zinc.io.zn
class ListBackends (argparse.Action) :
def __call__ (self, parser, namespace, values, option_string=None):
names = []
for _, name, ispkg in pkgutil.walk_packages(zinc.compil.__path__) :
if ispkg :
names.append(name)
names.sort()
width = max(len(n) for n in names)
for name in names :
try :
lang = zinc.compil.getlang(name)
print("".join([name.ljust(width + 4), lang.DESCRIPTION]))
for opt, (descr, default) in sorted(lang.OPTIONS.items()) :
print(" ", ("--%s=%r" % (opt, default)).ljust(14), " ", descr)
except :
pass
parser.exit()
parser = argparse.ArgumentParser(prog="zn", description="zinc is the net compiler")
parser.add_argument("-o", metavar="PATH", dest="output", default=None,
help="output code to PATH")
parser.add_argument("-n", metavar="NAME", dest="name", default="net",
help="name of the generated module")
parser.add_argument("-m", metavar="NAME", dest="module", default=None,
help="load SOURCE as a module and use NAME as net variable")
parser.add_argument("-l", nargs=0, action=ListBackends,
help="show available backends and exit")
parser.add_argument("source", metavar="SOURCE",
help="source file for the net to compile")
usage = io.StringIO()
parser.print_usage(usage)
parser.usage = usage.getvalue().strip() + " [--OPT=VAL ...]"
parser.epilog = "arguments --OPT=VAL add backend specific options"
args, opts = parser.parse_known_args()
options = {}
for o in opts :
if not o.startswith("--") :
parser.error("expected --OPT=VAL, got %r" % o)
try :
key, val = o[2:].split("=", 1)
except :
parser.error("expected --OPT=VAL, got %r" % o)
try :
options[key] = ast.literal_eval(val)
except :
options[key] = val
if args.module :
mod = importlib.import_module(args.source)
net = getattr(mod, args.module)
else :
try :
src = open(args.source)
except Exception as err :
parser.error("could not open %r (%s: %s)"
% (args.source, err.__class__.__name__, err))
net = zinc.io.zn.load(src)
net.build(name=args.name, saveto=args.output, **options)
......@@ -11,11 +11,11 @@ def getlang (name) :
module.name = name
return module
def build (lang, tree, saveto) :
def build (lang, tree, saveto, **options) :
if saveto is None :
out = io.StringIO()
elif isinstance(saveto, str) :
out = open(str, "w+")
out = open(saveto, "w+")
else :
try :
saveto.write("hello world!")
......@@ -31,12 +31,12 @@ def build (lang, tree, saveto) :
raise ValueError("%r object does not have expected file-like feature"
% saveto.__class__.__name__)
out = saveto
gen = lang.codegen.CodeGenerator(out)
gen = lang.codegen.CodeGenerator(out, **options)
gen.visit(tree)
out.flush()
out.seek(0)
if lang.INMEM :
mod = lang.build(tree, out, tree.name + lang.EXT)
mod = lang.build(tree, out, tree.name + lang.EXT, **options)
elif saveto is None :
try :
tmp = tempfile.NamedTemporaryFile(mode="w+", suffix=lang.EXT, delete=False)
......
import zinc.io.zn, sys
from . import build, CompilationError
net = zinc.io.zn.load(open(sys.argv[-1]))
ast = net.__ast__()
try :
build(net.lang, ast, None)
except CompilationError as err :
print(err.message())
......@@ -4,6 +4,10 @@ from zinc.compil import CompilationError, BaseDeclare
from . import codegen as codegen
from .rename import rename
DESCRIPTION = "CoffeeScript backend (http://coffeescript.org)"
OPTIONS = {"libpath": ("path to ZINC's CoffeeScript library", "."),
"main": ("whether to generate a main function", False)}
NONETYPE = True
BOOL = "Boolean"
EXT = ".coffee"
......@@ -12,7 +16,7 @@ INMEM = False
class Declare (BaseDeclare) :
pass
def build (ast, src, name) :
def build (ast, src, name, **options) :
try :
subprocess.check_output(["coffee", src], stderr=subprocess.STDOUT)
except Exception as err :
......
......@@ -4,6 +4,9 @@ from zinc.compil import BaseDeclare, CompilationError
from zinc.compil.go.rename import rename
from . import codegen
DESCRIPTION = "Golang backend (http://golang.org)"
OPTIONS = {}
NONETYPE = False
BOOL = "bool"
EXT = ".go"
......@@ -22,7 +25,7 @@ def update_gopath () :
elif path not in os.environ["GOPATH"].split(":") :
os.environ["GOPATH"] = ":".join([path, os.environ["GOPATH"]])
def build (ast, src, name) :
def build (ast, src, name, **options) :
update_gopath()
try :
subprocess.check_output(["go", "build", src], stderr=subprocess.STDOUT)
......
......@@ -4,6 +4,9 @@ from zinc.compil import CompilationError, BaseDeclare
from . import codegen as codegen
from .rename import rename
DESCRIPTION = "Python backend (http://www.python.org)"
OPTIONS = {}
NONETYPE = True
BOOL = "bool"
EXT = ".py"
......@@ -12,7 +15,7 @@ INMEM = True
class Declare (BaseDeclare) :
pass
def build (ast, src, name) :
def build (ast, src, name, **options) :
if isinstance(src, str) :
src = open(src)
try :
......
......@@ -98,7 +98,7 @@ class CodeGenerator (ast.CodeGenerator) :
self.write("\n%s" % inspect.getsource(lts))
self.write("\n%s" % inspect.getsource(main))
self.write("\nif __name__ == '__main__':"
"\n main()")
"\n main()\n")
def visit_DefineMarking (self, node) :
self.fill("from zinc.nets import Marking, mset, dot, hdict")
self.fill("event = collections.namedtuple('event', "
......
......@@ -16,8 +16,8 @@ class PetriNet (object) :
self._node = {}
def __repr__ (self) :
return "%s(%r, %r)" % (self.__class__.__name__, self.name, self.lang.name)
def build (self, name="net", saveto=None) :
return zinc.compil.build(self.lang, self.__ast__(name), saveto)
def build (self, name="net", saveto=None, **options) :
return zinc.compil.build(self.lang, self.__ast__(name), saveto, **options)
def __ast__ (self, name="net") :
ctx = zinc.compil.Context(net=self)
mod = ctx.Module(name,
......
#!/bin/sh
exec python3 -m zinc.cli "$@"