def main(): err = False try: f = open("src/port.json") except: err = True if err: try: Error.error("cannot find port.json") except EOFError as e: print(e, file=sys.stderr) sys.exit() file = f.read() port = json.loads(file) if len(sys.argv) > 1: if sys.argv[1] == "install": installPackage() elif sys.argv[1] == "uninstall": uninstallPackage() elif sys.argv[1] == "deploy": deploy(port) elif sys.argv[1] == "doc": doc(port) else: print("Unknown command "+sys.argv[1], file=sys.stderr) else: print("Need command", file=sys.stderr)
def initModule(moduleName): try: transforms[moduleName].init() except Exception as e: Error.error("Error " + str(e) + " happened when intializing syntax extension " + moduleName)
def condition_not_met(file, tags): f = open(file, "r") jsonLoads = json.loads(f.read()) for key in jsonLoads: if not key in tags: Error.error(file + ", unknown tag " + key) if jsonLoads[key] != tags[key]: return True return False
def loadRuntimeTypeData(): try: f = open(runtimeData, "rb") if os.stat(runtimeData).st_size == 0: Error.error("Runtime type data is empty, please recompile runtime") res = pickle.load(f) return res except FileNotFoundError: Error.error("Could not locate runtime")
def compile(self, opt= 0): js = self.toJS() try: f = open("lib/"+self.filename.replace("/", ".") + ".js", mode="w") f.write(js) f.close() except: Error.error("Compilation failed")
def importModule(path): moduleName = os.path.basename(os.path.splitext(path)[0]) spec = importlib.util.spec_from_file_location(moduleName, path) if not spec: Error.error("Cannot load transform from path " + path) foo = importlib.util.module_from_spec(spec) spec.loader.exec_module(foo) transforms[moduleName] = foo
def newPack(name): if name[0].lower() != name[0]: Error.error("package name must be lowercase") try: os.mkdir("src/" + name) f = open("src/" + name + "/port.json", mode="w") f.write(""" { "files": [] } """) except: Error.error("directory has no src folder")
def newPack(name): if name[0].lower() != name[0]: Error.error("package name must be lowercase") try: os.mkdir("src/" + name) f = open("src/"+name+"/port.json", mode= "w") f.write(""" { "files": [] } """) except: Error.error("directory has no source folder")
def getCompilationFiles(target): try: proj = open("src/port.json", mode="r") proj.close() except: Error.error("missing port.json in source folder") def getCompFiles(dir=""): file = {} for root, dirs, files in os.walk(dir, topdown=False): package = root if package == "src/": continue package = package[len("src/"):] file[package] = {"client": [], "full": [], "node": []} try: port = open("src/" + package + "/port.json", mode="r") except: Error.error("missing file port.json in package " + package + "") files = [] try: j = json.loads(port.read()) files.append((target, j["files"])) except KeyError: pass except json.decoder.JSONDecodeError as e: Error.error("In file port.json, in directory " + package + ", " + str(e)) if "client-files" in j and (target in ["full", "client"]): files.append(("client", j["client-files"])) if "node-files" in j and (target in ["full", "node"]): files.append(("node", j["node-files"])) if len(files) == 0: Error.error("no compilation files are specified in package " + package + "/port.json") for f in files: for name in f[1]: file[package][f[0]].append((root, name + ".top")) if root[0].lower() != root[0]: Error.error("package name must be lowercase") return file return getCompFiles("src/")
def linkWith(name): try: file = open("src/port.json", mode="r+") except: Error.error("missing port.json file in project") port = json.loads(file.read()) if name.endswith(".css"): port["linkCSS"].append(name) else: port["link"].append(name) file.write(json.dumps(port)) file.close()
def append(self, value): if value is None: raise Error.error( "expecting type string and got none, internal error") if self.target in [self.global_target, "full"]: if self.global_target == "full": if self.inAFunction: self.client_out_parts.append(value) self.node_out_parts.append(value) else: self.client_main_parts.append(value) self.node_main_parts.append(value) else: if self.inAFunction: self.out_parts.append(value) else: self.main_parts.append(value) elif self.target == "client": if self.inAFunction: self.client_out_parts.append(value) else: self.client_main_parts.append(value) elif self.target == "node": if self.inAFunction: self.node_out_parts.append(value) else: self.node_main_parts.append(value) elif self.target == "full": if self.inAFunction: self.out_parts.append(value) else: self.main_parts.append(value)
def iterate(i): try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() filenames_sources[package][i[1][:-4]] = r sources[package].append(r) if i[1][0].upper() == i[1][0]: Error.error("File name must be lowercase") filenames[package].append((i[0], i[1][:-4])) file.close() except FileNotFoundError: Error.error("File " + os.path.join(i[0], i[1]) + ", not found")
def iterate(i): try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() allsources.append(r) sources[_i][c].append(r) if i[1][0].upper() == i[1][0]: Error.error("file name must be lowercase") filenames[_i][c].append((c, i[1][:-4])) allfilenames.append((c, i[1][:-4])) file.close() except FileNotFoundError: Error.error("file " + i[1] + ", not found")
def linkWith(name): try: file = open("src/port.json", mode="r+") except: Error.error("missing port.json file in project") port = json.loads(file.read()) file.write(""" { "name": \"""" + port["name"] + """\", "version": """+str(port["version"]) + """, "link": """+str(port["link"]+[name]) + """, } """) file.close()
def newProj(name): if name[0].upper() != name[0]: Error.error("project name must be uppercase") try: os.mkdir(name) os.mkdir(name + "/" + "src") file = open(name + "/src/port.json", mode="w") file.write(""" { "name": \"""" + name + """\", "version": 0.0, "link": [] } """) file.close() os.mkdir(name + "/" + "lib") os.mkdir(name + "/" + "bin") except: Error.error("project already created")
def getCompFiles(dir= ""): file = {} for root, dirs, files in os.walk(dir, topdown=False): package = root if package == "src/": continue package = package[len("src/"):] file[package] = [] try: port = open("src/"+package+"/port.json", mode= "r") except: Error.error("missing file port.json in package "+package+"") try: j = json.loads(port.read()) files = j["files"] except KeyError: Error.error("missing property files in file "+package+"port.json") for name in files: file[package].append((root, name+".top")) if root[0].lower() != root[0]: Error.error("package name must be lowercase") return file
def compile(self, opt=0): target = self.global_target if target == "full": (node, client) = self.toJS(target) try: f = open("lib/" + self.filename.replace("/", ".") + "-node.js", mode="w") f.write(node) f.close() except Exception as e: Error.error("Compilation failed, " + str(e)) try: f = open("lib/" + self.filename.replace("/", ".") + "-client.js", mode="w") f.write(client) f.close() except Exception as e: Error.error("Compilation failed, " + str(e)) else: js = self.toJS(target) try: f = open("lib/" + self.filename.replace("/", ".") + "-" + target + ".js", mode="w") f.write(js) f.close() except Exception as e: Error.error("Compilation failed, " + str(e))
def newProj(name): if name[0].upper() != name[0]: Error.error("project name must be uppercase") try: os.mkdir(name) os.mkdir(name + "/" + "src") file = open(name + "/src/port.json", mode="w") file.write(""" { "name": \"""" + name + """\", "version": 0.0, "link": [], "linkCSS": [] } """) file.close() os.mkdir(name + "/" + "lib") os.mkdir(name + "/" + "bin") except: Error.error("project already created")
def link(filenames, output, run, opt, dev, linkWith, linkWithCSS, target, hotswap): needSocket = False if target == "node" and dev: linked = """(function(){ var fs = require("fs"); var io = require("socket.io").listen(8080); var watch = require("chokidar"); watch.watch('""" + output + """-client.js').on("change", (filename) => { //console.log("I think it changed"); if (filename) { fs.readFile('./""" + output + """-client.js', function (err, data) { if (!err) { data = String(data); io.sockets.emit('reload', data); } }); } }); watch.watch(""" + str([ i + "" for i in linkWithCSS ]) + """, {cwd: "../"}).on("change", (filename) => { fs.readFile("../" + filename, function (err, data) { if (!err) { console.log("\\n==== reloaded stylesheets ===="); data = String(data); io.sockets.emit('style', {name: filename, content: data}); } }) }) })();""" elif target == "client" and not run and dev: needSocket = True linked = "" socket = """ (function (){ var socket = io.connect('http://127.0.0.1:8080'); socket.on('reload', function (data) { console.log("\\n======== reloaded ========="); document.getElementById("code").innerHTML = ""; eval(data); }); socket.on('style', function (data) { var name = data.name; var content = data.content; console.log("\\n==== reloaded stylesheets ===="); document.getElementById(name).innerHTML = content; }); })();""" else: linked = "" if opt == 3: linked += "(function () {" import sys runtime = "" if hotswap and target == "client" else getRuntime( ) if target == "client" else getRuntimeNode() linked += runtime array = [] #print("====", target) for i in linkWith: try: f = open(i, mode="r") except: f.close() Error.error("cannot find file " + i + " to link") array.append(f.read()) f.close() linked += ";".join(array) css = "" if target == "client": for i in linkWithCSS: try: f = open(i, mode="r") except: f.close() Error.error("cannot find file " + i + " to link") css += '<style id="' + i + '">' + f.read() + "</style>" f.close() linked += "\n" for i in filenames: f = open("lib/" + i.replace("/", ".") + "-" + target + ".js", mode="r") linked += f.read() f.close() fjs = open("bin/" + output + "-" + target + ".js", mode="w") preCall = linked linked += "main_" + target + "Init();" if opt == 3 and target != "full": linked += "})()" fjs.write(linked) fjs.close() if opt == 3 and target != "full": args = [ "uglifyjs", "--compress", "--output", "bin/" + output + ".min-" + target + ".js", "--mangle", "--", "bin/" + output + "-" + target + ".js" ] subprocess.call(args, shell=False) output += ".min" linked = open("bin/" + output + "-" + target + ".js", "r").read() if target == "node": if run: execNode(output, dev) return if target == "full": return linked if opt == 3: output = output[:-len(".min")] f = open("bin/" + output + ".html", mode="w") html = """<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN"><HTML><HEAD><meta charset="UTF-8"><TITLE>""" + output + """</TITLE></HEAD><script>""" + linked + """</script></HTML>""" html = """ <!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML> <head> <meta charset="UTF-8"> <TITLE>""" + output + """</TITLE> <link rel="icon" href="favicon.ico" type="image/x-icon" /> """ + css + ( '<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script><script>' + socket + "</script>" if needSocket else '') + """ </head> <body> <div id= "code"></div> <script> """ + linked + """ </script> </body> </HTML>""" f.write(html) f.close() fjs.close() if run: exec(output)
def toCType(self): Error.error("no type introspection yet")
def start(run= False, dev= False, init= False): try: opt = 0 skip = 0 outputFile = "" for (iter, i) in enumerate(sys.argv[2:]): if skip > 0: continue skip -= 1 if i == "-O3": opt = 3 elif i == "-O2": opt = 2 elif i == "-o": outputFile = sys.argv[iter + 3] skip = 1 elif i == "-O1": opt = 1 else: Error.error("unknown argument '" + i + "'.") files = getCompilationFiles() allfilenames = [] allsources = [] sources = {} filenames = {} for c in files: sources[c] = [] filenames[c] = [] for i in files[c]: try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() allsources.append(r) sources[c].append(r) if i[1][0].upper() == i[1][0]: Error.error("file name must be lowercase") filenames[c].append((c, i[1][:-4])) allfilenames.append((c, i[1][:-4])) file.close() except FileNotFoundError: Error.error("file " + i[1] +", not found") if outputFile == "": port = open("src/port.json") data = port.read() outputFile = (json.loads(data)["name"]) port.close() if filenames == []: Error.error("no input files") """ import cProfile profile = cProfile.Profile() profile.enable() """ time1 = time() # print ("============= Compiling ==============\n") """ for i in lexed: print(i.token+"_"+i.type) """ lexed = Lexer.lex(sources, filenames) #print("lexed") declarations = Parser.Parser(lexed, filenames) declarations.files = files declarations.lexed = lexed declarations.filenames = filenames declarations.opt = opt declarations.compiled = {} declarations.externFuncs = {"main": []} ResolveSymbols.resolve(declarations) #print("declarations") if ImportParser.shouldCompile(False, "main", declarations): parser = Parser.Parser(lexed["main"], filenames["main"]) ResolveSymbols.insert(declarations, parser, only= True) parser.files = files parser.lexed = lexed parser.filenames = filenames parser.compiled = declarations.compiled parser.compiled["main"] = None parsed = parser.parse() parser.compiled["main"] = (True, (parsed, parser.externFuncs["main"])) import AST as Tree allCode = Tree.Root() if opt > 0: for d in parser.compiled: allCode.addNode(parser.compiled[d][1][0]) optimize(allCode, opt) #print("parsing") for i in parser.compiled: if parser.compiled[i][0]: CodeGen.CodeGen(i, parser.compiled[i][1][0], parser.compiled[i][1][1]).compile(opt=opt) l = CodeGen.link(parser.compiled, outputFile, run=run, opt= opt, dev= dev) print("Compilation took : "+str(time() - time1)) return (True, l) elif run: CodeGen.exec(outputFile) elif init: return (True, open("bin/"+outputFile+".js").read()) elif dev: return (False, "") print("Compilation took : "+str(time() - time1)) except EOFError as e: if dev: return (False, str(error)) else: print(e, file= sys.stderr)
from TopCompiler import topc from TopCompiler import Error import sys if __name__ == "__main__": if len(sys.argv) > 1: if sys.argv[1] == "new": if sys.argv[2] == "project": topc.newProj(sys.argv[3]) elif sys.argv[2] == "package": topc.newPack(sys.argv[3]) elif sys.argv[2] == "linkWith": topc.linkWith(sys.argv[3]) else: Error.error("invalid option to new" + sys.argv[2]) sys.exit() elif sys.argv[1] == "build": topc.start() elif sys.argv[1] == "run": topc.start(True) else: Error.error("invalid option " + sys.argv[1])
def tokenize(package, filename, s, tags, spos= 0, sline= 0, scolumn= 0): def notBack(iter): if iter == 0: return True if state.s[iter - 1] != "\\": return True return not notBack(iter - 1) state = LexerState(s) state.iter = spos state.line = sline state.filename = filename state.column = scolumn state.package = package state.amountOfSpaces = 0 state.inBrace = 0 lenOfS = len(s) in_if = 0 while state.iter < lenOfS: t = state.s[state.iter] completed = True if in_if > 0: if t == " " or t == "\n": if t == "\n": state.line += 1 state.tok = "" else: state.tok += t if state.tok == "#endif": in_if = False state.tok = "" state.iter += 1 state.iter += 1 continue if t == '"' and notBack(state.iter) and not (state.inComment or state.inChar or state.inCommentLine): state.inString = not state.inString if state.inString: state.pushTok() state.tok = '"' else: state.tok += '"' state.append(Token(state.tok, "str", state.line, state.column)) state.tok = "" elif t == "'" and notBack(state.iter) and not (state.inComment or state.inString or state.inCommentLine): state.inChar = not state.inChar if state.inChar: state.pushTok() state.tok = '"' else: state.tok += '"' state.append(Token(state.tok, "str", state.line, state.column)) state.tok = "" elif t == " " and not (state.inString or state.inComment or state.inChar or state.inCommentLine): state.pushTok() state.amountOfSpaces += 1 elif t == "{" and notBack(state.iter) and state.inString: state.inBrace += 1 state.tok += '"' state.append(Token(state.tok, "str", state.line, state.column)) state.append(Token("concat", "operator", state.line, state.column)) state.append(Token("(", "symbol", state.line, state.column)) state.inString = False state.tok = "" elif t == "}" and state.inBrace: state.inBrace -= 1 state.inString = True state.pushTok() state.append(Token(")", "symbol", state.line, state.column)) state.append(Token("concat", "operator", state.line, state.column)) state.tok = '"' elif t == "'" and not (state.inString or state.inComment or state.inCommentLine): state.inChar = not state.inChar if state.inChar: state.pushTok() state.tok = "'" else: state.tok += "'" state.pushTok() elif t == "/" and state.iter+1 < lenOfS and state.s[state.iter + 1] == "*" \ and not (state.inString or state.inComment or state.inChar or state.inCommentLine): state.inComment = True state.pushTok() state.iter += 1 state.column += 1 elif t == "*" and state.iter + 1 < lenOfS and state.s[state.iter + 1] == "/" \ and not (state.inString or state.inChar or state.inCommentLine): state.iter += 1 state.column += 1 state.inComment = False state.append(Token(state.tok, "comment", state.line, state.column)) state.tok = "" elif t == "/" and state.iter + 1 < lenOfS and state.s[state.iter + 1] == "/" \ and not (state.inString or state.inComment or state.inChar or state.inCommentLine): state.pushTok() state.iter += 1 state.column += 1 state.inCommentLine = True elif t == "`" and notBack(state.iter) and not (state.inComment or state.inChar or state.inCommentLine): state.pushTok() state.iter += 2 state.column += 2 s = state.s[state.iter-1] if s == "\\": state.iter += 1 s += state.s[state.iter-1] state.append(Token("'" + s + "'", "char", state.line, state.column)) if not (state.iter < lenOfS and state.s[state.iter] == "`"): Error.errorAst("Expecting `" + state.tok, state.package, state.filename, Token(state.tok, "", state.line, state.column)) elif t == "\n": if not (state.inString or state.inComment or state.inChar or state.inCommentLine): state.pushTok() if state.inCommentLine: state.tok = "" state.append(Token("\n", "symbol", state.line, state.column)) spaces = state.followedByNumSpace() state.append(Token(spaces, "indent", state.line, state.column)) state.column = -2 + spaces state.inCommentLine = False state.line += 1 global linesOfCode linesOfCode += 1 elif t == "." and len(state.s) >= state.iter+1 and str.isdigit(state.s[state.iter+1]): completed = False else: if not (state.inString or state.inComment or state.inChar or state.inCommentLine): if t in slSymbols: typ = "symbol" if t == "[": if state.iter > 0 and state.s[state.iter-1] == " ": typ = "whiteOpenS" state.pushTok() state.append(Token(t, typ, state.line, state.column)) elif t in slOperator: state.pushTok() if state.followedByNumSpace() == 0 and state.spaceBefore(): state.append(Token(t, "unary_operator", state.line, state.column)) else: state.append(Token(t, "operator", state.line, state.column)) else: completed = False lastLength = 0 tok = "" if state.iter+1 < len(state.s): end = state.s[state.iter] + state.s[state.iter+1] if end in ml2Operators: state.iter -= 1 state.pushTok() state.iter += 2 operators = end if operators in mlSymbols: state.append(Token(operators, "symbol", state.line, state.column)) else: if state.followedByNumSpace() == 0 and state.spaceBefore(): state.append(Token(operators, "unary_operator", state.line, state.column)) else: state.append(Token(operators, "operator", state.line, state.column)) completed = True if not completed: if state.s[state.iter] in ml1Operators: operators = state.s[state.iter] state.iter -= 1 state.pushTok() state.iter += 1 if operators in mlSymbols: state.append(Token(operators, "symbol", state.line, state.column)) else: if state.followedByNumSpace() == 0 and state.spaceBefore(): state.append(Token(operators, "unary_operator", state.line, state.column)) else: state.append(Token(operators, "operator", state.line, state.column)) completed = True else: completed = False if not completed: state.tok += t if not (t == " " and not (state.inString or state.inComment or state.inChar or state.inCommentLine)): state.amountOfSpaces = 0 state.iter += 1 state.column += 1 if state.tok == "#if": state.iter += 1 state.tok = "" while state.s[state.iter] != "\n" and state.iter < len(state.s): state.tok += state.s[state.iter] state.iter += 1 try: expects = json.loads(state.tok) except e: Error.error(filename, e) should_keep = True for key in expects: if not key in tags: Error.error(filename, ", unknown tag " + key) if expects[key] != tags[key]: should_keep = False break state.tok = "" if not should_keep: in_if = 1 if state.tok == "#endif": state.tok = "" in_if = 0 #print("'" + state.tok + "'", state.inString, state.inCommentLine, state.inComment, state.inChar) if not state.inCommentLine: state.pushTok() if state.inString or state.inComment: state.tokens[-1].error("EOF") state.append(Token("\n", "symbol", state.line-1, state.column)) state.append(Token(0, "indent", state.line, state.column)) state.append(Token("\n", "symbol", state.line, state.column)) state.append(Token(0, "indent", state.line, state.column)) return state.tokens
def link(filenames, output, run, debug, opt, dev, linkWith, linkWithCSS, target, hotswap): print(linkWith) needSocket = False if target == "client" and debug: terminal = open(__file__[0:__file__.rfind("/") + 1] + "terminal/bundle.html").read() needSocket = True linked = "" socket = "" else: linked = "" if opt == 3: linked = "(function(){" import sys runtime = "" if hotswap and target == "client" else getRuntime( ) if target == "client" else getRuntimeNode() linked += runtime css = "" if target == "client" and debug: linked += """log= function(d) { terminal.echo(d); }; log_unop = function(data, next) { terminal.echo(data); next(); }; function newAtom(arg) { previousState = { unary_read: unary_read, op_set: op_set, arg: arg, watch: atom_watch, events: [], toString: function(){ return "" } } calledBy.push("init -> "); recordNewValue(arg, function(){}); previousState.events.push(recordNewValue); return previousState } """ elif target == "client" and (dev and not hotswap): linked += """ function newAtom(arg) { previousState = { unary_read: unary_read, op_set: op_set, arg: arg, watch: atom_watch, events: [], toString: function(){ return "" } } return previousState } (function() { var socket = io.connect('http://127.0.0.1:9000/'); socket.on("connect", function() { socket.emit("new"); }) socket.on('reload', function (data) { log("=== reloaded ==="); document.getElementById("code").innerHTML = ""; document.getElementById("error").innerHTML = ""; eval(data); }); socket.on('comp_error', function (data) { document.getElementById("error").innerHTML = "<br>"+data+"<br>"; }); socket.on('style', function (data) { var name = data.name; var content = data.content; document.getElementById(name).innerHTML = content; }); socket.on("error", function(err) { isCode = false; terminal.set_prompt("> "); terminal.error(err); isCode = true; }) })() """ css += '<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>' array = [] # print("====", target) for i in linkWith: try: f = open(i, mode="r") except: f.close() Error.error("cannot find file " + i + " to link") array.append(f.read()) f.close() linked += ";".join(array) if target == "client": for i in linkWithCSS: try: f = open(i, mode="r") except: f.close() Error.error("cannot find file " + i + " to link") css += '<style id="' + i + '">' + f.read() + "</style>" f.close() linked += "\n" for i in filenames: f = open("lib/" + i.replace("/", ".") + "-" + target + ".js", mode="r") linked += f.read() f.close() fjs = open("bin/" + output + "-" + target + ".js", mode="w") preCall = linked linked += "main_" + target + "Init();" if opt == 3: linked += "})()" #import jsbeautifier #linked = jsbeautifier.beautify(linked) fjs.write(linked) fjs.close() if opt == 3 and target == "client": args = [ "uglifyjs", "--noerr", "--warn" "--compress", "unused,dead_code", "--output", output + ".min-" + target + ".js", "--mangle", "--", output + "-" + target + ".js" ] #args = ["closure-compiler", "--js", output + "-" + target + ".js", "--js_output_file", output + ".min-"+target+ ".js", "--warning_level", "QUIET", "--compilation_level", "ADVANCED"] subprocess.check_call(args, shell=False, cwd="bin") output += ".min" linked = open("bin/" + output + "-" + target + ".js", "r").read() if target == "node": if run: execNode(output, dev) return if target == "full": return linked if opt == 3: output = output[:-len(".min")] f = open("bin/" + output + ".html", mode="w") html = """ <!DOCTYPE html"> <HTML> <head> <meta charset="UTF-8"> <TITLE>""" + output + """</TITLE> <link rel="icon" href="favicon.ico" type="image/x-icon" /> """ + css + """ </head> <body> """ + ( '<div id="container" style="padding-top: 50px; margin-top: -10px; padding-bottom: 100px; color: white; margin-right: 10px; position: fixed; display: inline-block; float: left; height: 100%; background-color: black; width: 30%;"><button id="switchMode" style="position: fixed; color: black; z-index: 100000; top: 20; margin-left: 10px;so">Time Travel</button><div id="terminal" style="position: fixed; width: inherit; height: 90%;"></div></div><div id= "code" style= "float: right; width: 70%; position: relative;"></div>' if needSocket else '<div id= "code"></div>' ) + """ """ + ( '<div id="error" style="z-index: 10000000; width: 100%; background-color: #42f4eb; position: fixed; bottom: 0; font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif; padding-left: calc(50% - 123px);"></div>' if (dev and not hotswap) else "") + """ """ + ('<script>' + socket + "</script>" + terminal if needSocket else '') + """ <script> """ + linked + """ </script> </body> </HTML>""" f.write(html) f.close() fjs.close() if run: exec(output)
def getCompFiles(start, dir): linkWith = [] headerIncludePath = [] not_prefix = [] for root, dirs, files in os.walk(dir, topdown=True, followlinks=True): hasPort = False should_continue = False if root != "src/": for i in files: if i == "port.json": hasPort = True if i == "condition.json": if condition_not_met(root + "/" + i, tags): should_continue = root break if should_continue: not_prefix.append(should_continue) continue c = False for i in not_prefix: if root == i: not_prefix.remove(i) if root.startswith(i): print(root) c = True if c: continue package = os.path.basename( root) # [package.find("src/")+len("src/"):] for i in files: if not hasPort and i != "port.json" and i.endswith(".top"): package = i[:-4] if package in file and not package == "main": Error.error("multiple packages named " + package) file[package] = [(root, i)] #file[package].append((root, f + ".top")) package = root if root == start: continue package = os.path.basename( root) #package[package.find("src/")+len("src/"):] try: port = open(root + "/port.json", mode="r") except: continue Error.error("missing file port.json in package " + package + "") if package in file and not package == "main": Error.error("multiple packages named " + package) file[package] = [] files = [] try: j = json.loads(port.read()) port.close() files = j["files"] except KeyError: Error.error("In file port.js, in directory " + package + ", expecting attribute files") except json.decoder.JSONDecodeError as e: Error.error("In file port.json, in directory " + package + ", " + str(e)) (_linkWith, _headerIncludePath) = handleOptions( j, ["linkWith", "headerIncludePath"]) (_linkWith, _headerIncludePath) = [["src/" + package + "/" + c for c in i] for i in (_linkWith, _headerIncludePath)] linkWith += _linkWith headerIncludePath += _headerIncludePath for f in files: file[package].append((root, f + ".top")) if root[0].lower() != root[0]: Error.error("package name must be lowercase") return (linkWith, headerIncludePath)
def start(run=False, dev=False, init=False, hotswap=False, cache=False): global outputFile global didCompile try: opt = 0 skip = 0 outputFile = "" for (iter, i) in enumerate(sys.argv[2:]): if skip > 0: continue skip -= 1 if i == "-O3": opt = 3 elif i == "-O2": opt = 2 elif i == "-o": outputFile = sys.argv[iter + 3] skip = 1 elif i == "-O1": opt = 1 else: Error.error("unknown argument '" + i + "'.") port = open("src/port.json") data = port.read() jsonLoad = json.loads(data) port.close() def handleOptions(names): t = () for i in names: t += (jsonLoad[i] if i in jsonLoad else [], ) return t (linkCSSWithFiles, linkWithFiles, clientLinkWithFiles, nodeLinkWithFiles) = handleOptions( ["linkCSS", "linkWith", "linkWith-client", "linkWith-node"]) try: target = jsonLoad["target"] if not target in ["client", "node", "full"]: Error.error( "In global port.json file: unknown compile target, " + target) except KeyError: Error.error("must specify compilation target in port.json file") files = getCompilationFiles(target) allfilenames = [] allsources = [] sources = {} filenames = {} filenames = {"client": {}, "full": {}, "node": {}} sources = {"client": {}, "full": {}, "node": {}} for c in files: for _i in files[c]: filenames[_i][c] = [] sources[_i][c] = [] def iterate(i): try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() allsources.append(r) sources[_i][c].append(r) if i[1][0].upper() == i[1][0]: Error.error("file name must be lowercase") filenames[_i][c].append((c, i[1][:-4])) allfilenames.append((c, i[1][:-4])) file.close() except FileNotFoundError: Error.error("file " + i[1] + ", not found") for i in files[c][_i]: iterate(i) if outputFile == "": outputFile = (jsonLoad["name"]) global filenames_sources filenames_sources = {i: {} for i in sources["full"]} for _target in filenames: for package in filenames[_target]: for i, c in enumerate(filenames[_target][package]): filenames_sources[package][ c[1]] = sources[_target][package][i] if not "main" in filenames_sources: Error.error( "Project must have a main package, from where to start the code for the client" ) time1 = time() """ import cProfile profile = cProfile.Profile() profile.enable() #""" globalTarget = target didCompile = False def compile(target, sources, filenames, former=None): lexed = Lexer.lex(sources, filenames) declarations = Parser.Parser(lexed, filenames) declarations.hotswap = False declarations.shouldCompile = {} declarations.atoms = 0 declarations.atomTyp = False declarations.jsFiles = clientLinkWithFiles + linkWithFiles if cache: declarations.scope = cache.scope declarations.interfaces = cache.interfaces declarations.structs = cache.structs declarations.hotswap = hotswap declarations.allImports = cache.allImports declarations.atomTyp = cache.atomTyp if former: #print("inserting", target) ResolveSymbols.insert(former, declarations, only=True, copy=True) #print(declarations.scope["_global"]) declarations.files = files declarations.lexed = lexed declarations.filenames = filenames declarations.opt = opt declarations.compiled = {} declarations.externFuncs = {"main": []} declarations.filenames_sources = filenames_sources declarations.global_target = target ResolveSymbols.resolve(declarations) #print("declarations") #print(declarations.shouldCompile) if (dev and run) or ImportParser.shouldCompile( False, "main", declarations): parser = Parser.Parser(lexed["main"], filenames["main"]) ResolveSymbols.insert(declarations, parser, only=True) parser.files = files parser.global_target = target parser.lexed = lexed parser.filenames = filenames parser.compiled = declarations.compiled parser.compiled["main"] = None parsed = parser.parse() parser.compiled["main"] = (True, (parsed, parser.externFuncs["main"])) import AST as Tree allCode = Tree.Root() """ if opt > 0: for d in parser.compiled: allCode.addNode(parser.compiled[d][1][0]) optimize(allCode, opt) """ #print("parsing") for i in parser.compiled: if parser.compiled[i][0]: CodeGen.CodeGen(i, parser.compiled[i][1][0], parser.compiled[i][1][1], target).compile(opt=opt) if target == "full": _linkCSSWithFiles = linkCSSWithFiles client_linkWithFiles = linkWithFiles + clientLinkWithFiles node_linkWithFiles = linkWithFiles + nodeLinkWithFiles a = CodeGen.link(parser.compiled, outputFile, hotswap=hotswap, run=False, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=client_linkWithFiles, target="client") if run: import webbrowser webbrowser.open("http://127.0.0.1:3000/") l = CodeGen.link(parser.compiled, outputFile, hotswap=hotswap, run=run, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=node_linkWithFiles, target="node") else: _linkCSSWithFiles = [] if target != "client" else linkCSSWithFiles _linkWithFiles = linkWithFiles + nodeLinkWithFiles if target == "node" else linkWithFiles + clientLinkWithFiles if target == "client" else [] l = CodeGen.link(parser.compiled, outputFile, run=run, opt=opt, dev=dev, hotswap=hotswap, linkWithCSS=_linkCSSWithFiles, linkWith=_linkWithFiles, target=target) didCompile = True print("\n======== recompiling =========") return parser elif run: if target == "full": if run: import webbrowser webbrowser.open("http://127.0.0.1:3000/") CodeGen.execNode(outputFile, dev) else: CodeGen.exec(outputFile) return declarations fil = filenames[target] sour = sources[target] return compile(target, sour, fil) except EOFError as e: if dev: Error.error(str(e)) else: print(e, file=sys.stderr) if didCompile: print("Compilation took : " + str(time() - time1))
from TopCompiler import topc from TopCompiler import Error import sys if __name__ == "__main__": if len(sys.argv) > 1: if sys.argv[1] == "new": if sys.argv[2] == "project": topc.newProj(sys.argv[3]) elif sys.argv[2] == "package": topc.newPack(sys.argv[3]) elif sys.argv[2] == "linkWith": topc.linkWith(sys.argv[3]) else: Error.error("invalid option to new"+sys.argv[2]) sys.exit() elif sys.argv[1] == "build": topc.start() elif sys.argv[1] == "run": topc.start(True) else: Error.error("invalid option "+sys.argv[1])
def link(compiled, outputFile, includes, opt, hotswap, debug, linkWith, headerIncludePath, target, dev, context, runtimeBuild, to_obj): #Add Option to change compiler print(compiled) topRuntime = "" (context, mainC) = context if not runtimeBuild: topRuntime = open(os.path.dirname(__file__) + "/runtime/runtimeTop.c") topRuntime = topRuntime.read() includes = "".join(includes) linkedCode = [includes, hRuntimeCode, context, cRuntimeCode, topRuntime, "struct _global_Context _global_context;"] for c in compiled: f = open("lib/" + c + ".h", mode="r") linkedCode.append(f.read()) f.close() for c in compiled: f = open("lib/" + c + ".c", mode="r") linkedCode.append(f.read()) f.close() print_size = 'printf("offset of cases %llu, %llu", sizeof(struct ecs_Slot_model_ModelRenderer), sizeof(struct model_ModelRenderer)); return 0;' linkedCode.append(f"int main() {{ \n_globalInitTypes(); _globalInit(); _global_init_c_runtime(); \n {mainC}; \n mainInitTypes(); mainInit(); return 0; }};") f = open("bin/" + outputFile + ".c", mode="w") f.write("\n".join(linkedCode)) f.close() clang_commands = ["clang", "bin/" + outputFile + ".c"] #linkWith.append("C:\\Program Files (x86)\Windows Kits\\10\Lib\\10.0.17134.0\\um\\x64\\.lib") for i in linkWith: clang_commands.append(i) for i in headerIncludePath: clang_commands.append("-iwithprefix") clang_commands.append(i) """ glfw3.lib; opengl32.lib; kernel32.lib; user32.lib; gdi32.lib; winspool.lib; shell32.lib; ole32.lib; oleaut32.lib; uuid.lib; comdlg32.lib; advapi32.lib; glfw3.lib """ if debug: debug = ["-g", "-gcodeview", "-O" + str(opt)] else: debug = ["-O" + str(opt)] #["-g", "-gcodeview"] if to_obj: clang_commands += [ "-c", "-o", "bin/" + outputFile + ".o"] + debug + ["-Wno-incompatible-pointer-types", "-Wno-visibility", "-Wno-return-type", "-Wno-unused-value"] else: clang_commands += [ "-o", "bin/" + outputFile + ".exe"] + debug + ["-Wno-incompatible-pointer-types", "-Wno-visibility", "-Wno-return-type", "-Wno-unused-value"] print(" ".join(clang_commands),"\n") try: subprocess.check_call(clang_commands) except: Error.error("\nC code failed to compile")
def exec(outputFile): try: subprocess.check_call(["./bin/"+outputFile + ".exe"]) except subprocess.CalledProcessError as e: Error.error(e)
def start(run=False, _raise=False, dev=False, doc=False, init=False, _hotswap=False, cache=False, debug=False): global modified_ modified_ = {} time1 = time() hotswap = dev and not run global outputFile global didCompile global global_parser didCompile = False try: opt = 0 skip = 0 outputFile = "" for (iter, i) in enumerate(sys.argv[2:]): if skip > 0: continue skip -= 1 if i == "-O3": opt = 3 elif i == "-O2": opt = 2 elif i == "-o": outputFile = sys.argv[iter + 3] skip = 1 elif i == "-O1": opt = 1 else: Error.error("unknown argument '" + i + "'.") if not _hotswap and opt == 0: cache = saveParser.load() try: port = open("src/port.json") data = port.read() port.close() except FileNotFoundError: Error.error("Missing file port.json in folder src") try: jsonLoad = json.loads(data) except Exception as e: Error.error("invalid json in port.json, " + str(e)) try: target = jsonLoad["target"] if not target in ["client", "node", "full"]: Error.error( "In global port.json file: unknown compile target, " + target) except KeyError: Error.error("must specify compilation target in port.json file") (linkCSSWithFiles, linkWithFiles, clientLinkWithFiles, nodeLinkWithFiles, transforms) = handleOptions(jsonLoad, [ "linkCSS", "linkWith", "linkWith-client", "linkWith-node", "register-transforms" ]) (linkCSSWithFiles, linkWithFiles, clientLinkWithFiles, nodeLinkWithFiles) = [[ ("", c) for c in i ] for i in (linkCSSWithFiles, linkWithFiles, clientLinkWithFiles, nodeLinkWithFiles)] for i in transforms: Module.importModule(os.path.abspath(i)) (_linkCSSWithFiles, _linkWithFiles, _clientLinkWithFiles, _nodeLinkWithFiles, files, transforms) = getCompilationFiles(target) linkCSSWithFiles += _linkCSSWithFiles linkWithFiles += _linkWithFiles clientLinkWithFiles += _clientLinkWithFiles nodeLinkWithFiles += _nodeLinkWithFiles global filenames_sources sources = {} filenames = {} for package in files: #if not hotswap or (hotswap and modified(files[c], c)): def iterate(i): try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() filenames_sources[package][i[1][:-4]] = r sources[package].append(r) if i[1][0].upper() == i[1][0]: Error.error("File name must be lowercase") filenames[package].append((i[0], i[1][:-4])) file.close() except FileNotFoundError: Error.error("File " + os.path.join(i[0], i[1]) + ", not found") sources[package] = [] if not hotswap or (hotswap and modified( target, cache.files[package], package)): filenames[package] = [] filenames_sources[package] = {} for i in files[package]: iterate(i) else: for (pkg, name) in cache.files[package]: sources[package].append( filenames_sources[package][name[:-4]]) filenames[package] = cache.files[package] if outputFile == "": outputFile = (jsonLoad["name"]) if not "main" in filenames_sources: Error.error( "Project must have a main package, from where to start the code for the client" ) """ import cProfile profile = cProfile.Profile() profile.enable() #""" globalTarget = target didCompile = False def compile(target, sources, filenames, former=None): global global_parser global_parser = cache #print(cache.usedModules) lexed = Lexer.lex(target, sources, filenames, files, cache, cache.lexed if cache else {}, transforms) declarations = Parser.Parser(lexed, filenames) declarations.hotswap = False declarations.shouldCompile = {} declarations.atoms = 0 declarations.atomTyp = False declarations.outputFile = outputFile declarations.jsFiles = [ b for (a, b) in clientLinkWithFiles + linkWithFiles + linkCSSWithFiles + nodeLinkWithFiles ] declarations.cssFiles = linkCSSWithFiles declarations.transforms = transforms declarations.usedModules = {} global_parser = declarations if cache: declarations.scope = cache.scope declarations.interfaces = cache.interfaces declarations.structs = cache.structs declarations.hotswap = hotswap declarations.allImports = cache.allImports declarations.atomTyp = cache.atomTyp declarations.hotswap = True declarations.usedModules = cache.usedModules if former: #print("inserting", target) ResolveSymbols.insert(former, declarations, only=True, copy=True) #print(declarations.scope["_global"]) declarations.files = files declarations.lexed = lexed declarations.filenames = filenames declarations.opt = opt declarations.compiled = {} declarations.externFuncs = {"main": []} declarations.filenames_sources = filenames_sources declarations.global_target = target declarations.output_target = target declarations.didCompile = False if (dev and run): clearMain(declarations) ResolveSymbols.resolve(declarations) #print("declarations") #print(declarations.shouldCompile) if opt == 3 or doc or ImportParser.shouldCompile( False, "main", declarations): parser = Parser.Parser(lexed["main"], filenames["main"]) parser.package = "main" ResolveSymbols.insert(declarations, parser, only=True) parser.files = files parser.global_target = target parser.output_target = target parser.lexed = lexed parser.filenames = filenames parser.compiled = declarations.compiled parser.compiled["main"] = None parser.dev = dev parsed = parser.parse() parser.compiled["main"] = (True, (parsed, [])) global_parser = parser import AST as Tree allCode = Tree.Root() """ if opt > 0: for d in parser.compiled: allCode.addNode(parser.compiled[d][1][0]) optimize(allCode, opt) """ #print("parsing") if doc: return parser canStartWith = [''] order_of_modules = [] for i in parser.compiled: tmp = os.path.dirname(parser.filenames[i][0][0]) dir = tmp[tmp.find("packages") + len("packages") + 1:tmp.rfind("src") - 1] canStartWith.append(dir) if parser.compiled[i][0]: CodeGen.CodeGen(order_of_modules, i, parser.compiled[i][1][0], parser.compiled[i][1][1], target, opt).compile(opt=opt) order_of_modules.append("main") for i in parser.lexed: parser.usedModules[i] = datetime.datetime.now() _linkCSSWithFiles = [ i for (d, i) in linkCSSWithFiles if d in canStartWith ] _clientLinkWithFiles = [ i for (d, i) in clientLinkWithFiles if d in canStartWith ] _nodeLinkWithFiles = [ i for (d, i) in nodeLinkWithFiles if d in canStartWith ] _linkWithFiles = [ i for (d, i) in linkWithFiles if d in canStartWith ] compiled = order_of_modules #parser.compiled if not dev and not _raise: saveParser.save(parser) print("\n======== recompiling =========") print("Compilation took : " + str(time() - time1)) if target == "full": client_linkWithFiles = _linkWithFiles + _clientLinkWithFiles node_linkWithFiles = _linkWithFiles + _nodeLinkWithFiles if run: a = CodeGen.link(compiled, outputFile, hotswap=hotswap, run=False, debug=debug, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=client_linkWithFiles, target="client") print("Open website, at", "http://127.0.0.1:3000/") l = CodeGen.link(compiled, outputFile, debug=debug, hotswap=hotswap, run=run, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=node_linkWithFiles, target="node") else: l = CodeGen.link(compiled, outputFile, debug=debug, hotswap=hotswap, run=run, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=node_linkWithFiles, target="node") a = CodeGen.link(compiled, outputFile, hotswap=hotswap, run=False, debug=debug, opt=opt, dev=dev, linkWithCSS=_linkCSSWithFiles, linkWith=client_linkWithFiles, target="client") else: _link_CSSWithFiles = [] if target != "client" else _linkCSSWithFiles _linkWithFiles = _linkWithFiles + _nodeLinkWithFiles if target == "node" else _linkWithFiles + _clientLinkWithFiles if target == "client" else [] l = CodeGen.link(compiled, outputFile, run=run, opt=opt, dev=dev, hotswap=hotswap, linkWithCSS=_link_CSSWithFiles, debug=debug, linkWith=_linkWithFiles, target=target) didCompile = True parser.didCompile = True return parser elif run: if target == "full": print("Open website, at", "http://127.0.0.1:3000/") CodeGen.execNode(outputFile, dev) else: if target == "node": CodeGen.execNode(outputFile, dev) else: CodeGen.exec(outputFile) return declarations fil = filenames sour = sources c = compile(target, sour, fil) return c except (EOFError, ArithmeticError) as e: if dev or _raise: Error.error(str(e)) else: print(e, file=sys.stderr) if didCompile: print("Compilation took : " + str(time() - time1))
def getCompFiles(start, dir): linkCSSWithFiles = [] linkWithFiles = [] clientLinkWithFiles = [] nodeLinkWithFiles = [] for root, dirs, files in os.walk(dir, topdown=False, followlinks=True): for i in files: if root == start and i != "port.json" and i.endswith(".top"): _package = i[:-4] file[_package] = [(root, i)] #file[package].append((root, f + ".top")) files = [] if root.endswith("node_modules") or "/node_modules/" in root: continue package = root if package == start: continue package = package[package.find("src/") + len("src/"):] if package in file and not package == "main": Error.error("multiple packages named " + package) file[package] = [] try: port = open(start + package + "/port.json", mode="r") except: continue try: j = json.loads(port.read()) port.close() files = j["files"] except KeyError: Error.error("In file port.js, in directory " + package + ", expecting attribute files") except json.decoder.JSONDecodeError as e: Error.error("In file port.json, in directory " + package + ", " + str(e)) (_linkCSSWithFiles, _linkWithFiles, _clientLinkWithFiles, _nodeLinkWithFiles) = handleOptions( j, ["linkCSS", "linkWith", "linkWith-client", "linkWith-node"]) (_linkCSSWithFiles, _linkWithFiles, _clientLinkWithFiles, _nodeLinkWithFiles) = [[ "src/" + package + "/" + c for c in i ] for i in [ _linkCSSWithFiles, _linkWithFiles, _clientLinkWithFiles, _nodeLinkWithFiles ]] linkCSSWithFiles += _linkCSSWithFiles linkWithFiles += _linkWithFiles clientLinkWithFiles += _clientLinkWithFiles nodeLinkWithFiles += _nodeLinkWithFiles try: transforms[package] = j["transforms"] except KeyError: pass for f in files: file[package].append((root, f + ".top")) if root[0].lower() != root[0]: Error.error("package name must be lowercase") return (linkCSSWithFiles, linkWithFiles, clientLinkWithFiles, nodeLinkWithFiles)
def removeModule(moduleName): try: transforms[moduleName].remove() except Exception as e: Error.error("Error " + str(e) + " happened when removing syntax extension " + moduleName)
def compile(target, sources, filenames, former=None): global global_parser global_parser = cache #print(cache.usedModules) lexed = Lexer.lex(target, sources, filenames, files, cache, {}, tags) print("Lexed and parsed : " + str(Lexer.linesOfCode)) declarations = Parser.Parser(lexed, filenames) declarations.hotswap = False declarations.shouldCompile = {} declarations.atoms = 0 declarations.atomTyp = False declarations.outputFile = outputFile declarations.usedModules = {} declarations.path = os.path.abspath("") declarations.compilingRuntime = compileRuntime global_parser = declarations if cache: declarations.scope = cache.scope declarations.interfaces = cache.interfaces declarations.structs = cache.structs declarations.hotswap = hotswap declarations.allImports = cache.allImports declarations.atomTyp = cache.atomTyp declarations.hotswap = True declarations.usedModules = cache.usedModules declarations.specifications = cache.specifications declarations.includes = cache.includes Types.genericTypes = cache.generatedGenericTypes Types.inProjectTypes = { name: None for name in Types.genericTypes } from TopCompiler import Tree Tree.casted = cache.casted declarations.contextFields = cache.contextFields declarations.contextType = {} for package in declarations.contextFields: declarations.contextType.update( declarations.contextFields[package]) if former: #print("inserting", target) ResolveSymbols.insert(former, declarations, only=True, copy=False) #print(declarations.scope["_global"]) declarations.files = files declarations.lexed = lexed declarations.filenames = filenames declarations.opt = opt declarations.compiled = coll.OrderedDict() declarations.externFuncs = {"main": []} declarations.filenames_sources = filenames_sources declarations.global_target = target declarations.output_target = target declarations.didCompile = False declarations.linkWith = linkWith if (dev and run): clearMain(declarations) #print("declarations") #print(declarations.shouldCompile) declarations.setGlobalData(compileRuntime) ResolveSymbols.resolve(declarations) if opt == 3 or doc or ImportParser.shouldCompile( False, "main", declarations): print("Recompiling") parser = Parser.Parser(lexed["main"], filenames["main"]) parser.package = "main" ResolveSymbols.insert(declarations, parser, only=True) parser.files = files parser.global_target = target parser.output_target = target parser.lexed = lexed parser.filenames = filenames parser.compiled = declarations.compiled parser.compiled["main"] = None parser.contextFields["main"] = {} parser.dev = dev parser.sc = True parsed = parser.parse() parser.compiled["main"] = (True, (parsed, [])) global_parser = parser import AST as Tree allCode = Tree.Root() """ if opt > 0: for d in parser.compiled: allCode.addNode(parser.compiled[d][1][0]) optimize(allCode, opt) """ #print("parsing") if doc: return parser canStartWith = [''] order_of_modules = [] compiled = parser.order_of_modules # order_of_modules #parser.compiled typesInContext = [] for i in parser.compiled: parser.package = i sc = parser.compiled[i][0] if sc or not cache: SimplifyAst.resolveGeneric(parser, parser.compiled[i][1][0]) #generatedTypes = Types.genericTypes #Types.genericTypes = {} contextCCode = CodeGen.buildContext(parser) """ for i in parser.compiled: parser.package = i sc = parser.compiled[i][0] if not parser.compiled[i][0]: if cache and i in cache.generatedTypesPerPackage: parser.generatedTypesPerPackage[i] = cache.generatedTypesPerPackage[i] for typ in cache.generatedTypesPerPackage[i]: Types.genericTypes[typ] = None Types.inProjectTypes[typ] = None """ #print(Types.genericTypes) #generatedTypes.update(Types.genericTypes) #Types.genericTypes = generatedTypes #if not compileRuntime: # addTypes(removedTypes) # contextCCode = CodeGen.buildContext(parser.contextType) includes = [] for i in compiled: tmp = os.path.dirname(parser.filenames[i][0][0]) dir = tmp[tmp.find("packages") + len("packages") + 1:tmp.rfind("src") - 1] canStartWith.append(dir) sc = parser.compiled[i][0] if sc or not cache: inc = CodeGen.CodeGen(parser, order_of_modules, i, parser.compiled[i][1][0], parser.compiled[i][1][1], target, opt, debug=debug).compile(opt=opt) includes.extend(inc) parser.includes[i] = inc else: includes.extend(parser.includes[i]) order_of_modules.append("main") for i in parser.lexed: parser.usedModules[i] = datetime.datetime.now() _linkWith = [i for (d, i) in linkWith if d in canStartWith] _headerIncludePath = [ i for (d, i) in headerIncludePath if d in canStartWith ] parser.generatedGenericTypes = Types.genericTypes if compileRuntime: #not dev and not _raise: deleteQue = [] for c in parser.generatedGenericTypes: parser.generatedGenericTypes[c] = None if c in ["_global_Allocator", "_global_Type"]: deleteQue.append(c) for c in deleteQue: del parser.generatedGenericTypes[c] timeForCodeAnalysis = time() - beforeLoad print("Code Analysis : " + str(timeForCodeAnalysis)) if False: #not compileRuntime: c = [] for i in compiled: sc = parser.compiled[i][0] if sc: c.append(i) else: header = "lib/" + i + ".h" header = os.path.abspath(header) includes.append('#include "' + header + '"\n') print(includes) prelink = CodeGen.link( c, "recompiled_" + outputFile, to_obj=True, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=[], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) l = CodeGen.link([], outputFile, to_obj=True, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=[], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) if not to_obj: l = CodeGen.link([], outputFile, to_obj=to_obj, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=_linkWith + [ outputFile + ".o", "recompiled_" + outputFile + ".o" ], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) else: l = CodeGen.link(compiled, outputFile, to_obj=to_obj, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=_linkWith, headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) if compileRuntime: saveParser.save(parser, compileRuntime) print("\n======== recompiling =========") print("Compilation took : " + str(time() - time1)) print("") if run: if to_obj: Error.error("Cannot run .obj") CodeGen.exec(outputFile) didCompile = True parser.didCompile = True return parser elif run: CodeGen.exec(outputFile) return declarations
def start(run=False, _raise=False, dev=False, doc=False, init=False, _hotswap=False, cache=False, debug=False, compileRuntime=False): global modified_ modified_ = {} time1 = time() hotswap = dev and not run global outputFile global didCompile global global_parser didCompile = False try: opt = 0 skip = 0 to_obj = False outputFile = "" for (iter, i) in enumerate(sys.argv[2:]): if skip > 0: continue skip -= 1 if i == "-O3": opt = 3 elif i == "-O2": opt = 2 elif i == "-o": outputFile = sys.argv[iter + 3] skip = 1 elif i == "-O1": opt = 1 elif i == "-c": to_obj = True else: Error.error("unknown argument '" + i + "'.") beforeLoad = time() if not _hotswap and opt == 0 and not compileRuntime: #cache = saveParser.load(compileRuntime) pass try: port = open("src/port.json") data = port.read() port.close() except FileNotFoundError: Error.error("Missing file port.json in folder src") try: jsonLoad = json.loads(data) except Exception as e: Error.error("invalid json in port.json, " + str(e)) tags = {} if "tags" in jsonLoad: tags = jsonLoad["tags"] try: target = jsonLoad["target"] if not target in ["osx", "windows"]: Error.error( "In global port.json file: unknown compile target, " + target) except KeyError: Error.error("must specify compilation target in port.json file") (linkWith, headerIncludePath, files) = handleOptions(jsonLoad, ["linkWith", "headerIncludePath", "files"]) (linkWith, headerIncludePath, files) = [[("", c) for c in i] for i in (linkWith, headerIncludePath, files)] (_linkWith, _headerIncludePath, files) = getCompilationFiles(target, tags) linkWith += _linkWith headerIncludePath += _headerIncludePath global filenames_sources sources = {} filenames = {} for package in files: #if not hotswap or (hotswap and modified(files[runtime], runtime)): def iterate(i): try: file = open(os.path.join(i[0], i[1]), mode="r") r = file.read() filenames_sources[package][i[1][:-4]] = r sources[package].append(r) if i[1][0] != i[1][0].lower(): Error.error("File name must be lowercase") filenames[package].append((i[0], i[1][:-4])) file.close() except FileNotFoundError: Error.error("File " + os.path.join(i[0], i[1]) + ", not found") sources[package] = [] if not hotswap or (hotswap and modified( target, cache.files[package], package)): filenames[package] = [] filenames_sources[package] = {} for i in files[package]: iterate(i) else: for (pkg, name) in cache.files[package]: sources[package].append( filenames_sources[package][name[:-4]]) filenames[package] = cache.files[package] if outputFile == "": outputFile = (jsonLoad["name"]) if not "main" in filenames_sources: Error.error( "Project must have a main package, from where to start the code for the client" ) """ import cProfile profile = cProfile.Profile() profile.enable() #""" globalTarget = target didCompile = False def compile(target, sources, filenames, former=None): global global_parser global_parser = cache #print(cache.usedModules) lexed = Lexer.lex(target, sources, filenames, files, cache, {}, tags) print("Lexed and parsed : " + str(Lexer.linesOfCode)) declarations = Parser.Parser(lexed, filenames) declarations.hotswap = False declarations.shouldCompile = {} declarations.atoms = 0 declarations.atomTyp = False declarations.outputFile = outputFile declarations.usedModules = {} declarations.path = os.path.abspath("") declarations.compilingRuntime = compileRuntime global_parser = declarations if cache: declarations.scope = cache.scope declarations.interfaces = cache.interfaces declarations.structs = cache.structs declarations.hotswap = hotswap declarations.allImports = cache.allImports declarations.atomTyp = cache.atomTyp declarations.hotswap = True declarations.usedModules = cache.usedModules declarations.specifications = cache.specifications declarations.includes = cache.includes Types.genericTypes = cache.generatedGenericTypes Types.inProjectTypes = { name: None for name in Types.genericTypes } from TopCompiler import Tree Tree.casted = cache.casted declarations.contextFields = cache.contextFields declarations.contextType = {} for package in declarations.contextFields: declarations.contextType.update( declarations.contextFields[package]) if former: #print("inserting", target) ResolveSymbols.insert(former, declarations, only=True, copy=False) #print(declarations.scope["_global"]) declarations.files = files declarations.lexed = lexed declarations.filenames = filenames declarations.opt = opt declarations.compiled = coll.OrderedDict() declarations.externFuncs = {"main": []} declarations.filenames_sources = filenames_sources declarations.global_target = target declarations.output_target = target declarations.didCompile = False declarations.linkWith = linkWith if (dev and run): clearMain(declarations) #print("declarations") #print(declarations.shouldCompile) declarations.setGlobalData(compileRuntime) ResolveSymbols.resolve(declarations) if opt == 3 or doc or ImportParser.shouldCompile( False, "main", declarations): print("Recompiling") parser = Parser.Parser(lexed["main"], filenames["main"]) parser.package = "main" ResolveSymbols.insert(declarations, parser, only=True) parser.files = files parser.global_target = target parser.output_target = target parser.lexed = lexed parser.filenames = filenames parser.compiled = declarations.compiled parser.compiled["main"] = None parser.contextFields["main"] = {} parser.dev = dev parser.sc = True parsed = parser.parse() parser.compiled["main"] = (True, (parsed, [])) global_parser = parser import AST as Tree allCode = Tree.Root() """ if opt > 0: for d in parser.compiled: allCode.addNode(parser.compiled[d][1][0]) optimize(allCode, opt) """ #print("parsing") if doc: return parser canStartWith = [''] order_of_modules = [] compiled = parser.order_of_modules # order_of_modules #parser.compiled typesInContext = [] for i in parser.compiled: parser.package = i sc = parser.compiled[i][0] if sc or not cache: SimplifyAst.resolveGeneric(parser, parser.compiled[i][1][0]) #generatedTypes = Types.genericTypes #Types.genericTypes = {} contextCCode = CodeGen.buildContext(parser) """ for i in parser.compiled: parser.package = i sc = parser.compiled[i][0] if not parser.compiled[i][0]: if cache and i in cache.generatedTypesPerPackage: parser.generatedTypesPerPackage[i] = cache.generatedTypesPerPackage[i] for typ in cache.generatedTypesPerPackage[i]: Types.genericTypes[typ] = None Types.inProjectTypes[typ] = None """ #print(Types.genericTypes) #generatedTypes.update(Types.genericTypes) #Types.genericTypes = generatedTypes #if not compileRuntime: # addTypes(removedTypes) # contextCCode = CodeGen.buildContext(parser.contextType) includes = [] for i in compiled: tmp = os.path.dirname(parser.filenames[i][0][0]) dir = tmp[tmp.find("packages") + len("packages") + 1:tmp.rfind("src") - 1] canStartWith.append(dir) sc = parser.compiled[i][0] if sc or not cache: inc = CodeGen.CodeGen(parser, order_of_modules, i, parser.compiled[i][1][0], parser.compiled[i][1][1], target, opt, debug=debug).compile(opt=opt) includes.extend(inc) parser.includes[i] = inc else: includes.extend(parser.includes[i]) order_of_modules.append("main") for i in parser.lexed: parser.usedModules[i] = datetime.datetime.now() _linkWith = [i for (d, i) in linkWith if d in canStartWith] _headerIncludePath = [ i for (d, i) in headerIncludePath if d in canStartWith ] parser.generatedGenericTypes = Types.genericTypes if compileRuntime: #not dev and not _raise: deleteQue = [] for c in parser.generatedGenericTypes: parser.generatedGenericTypes[c] = None if c in ["_global_Allocator", "_global_Type"]: deleteQue.append(c) for c in deleteQue: del parser.generatedGenericTypes[c] timeForCodeAnalysis = time() - beforeLoad print("Code Analysis : " + str(timeForCodeAnalysis)) if False: #not compileRuntime: c = [] for i in compiled: sc = parser.compiled[i][0] if sc: c.append(i) else: header = "lib/" + i + ".h" header = os.path.abspath(header) includes.append('#include "' + header + '"\n') print(includes) prelink = CodeGen.link( c, "recompiled_" + outputFile, to_obj=True, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=[], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) l = CodeGen.link([], outputFile, to_obj=True, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=[], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) if not to_obj: l = CodeGen.link([], outputFile, to_obj=to_obj, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=_linkWith + [ outputFile + ".o", "recompiled_" + outputFile + ".o" ], headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) else: l = CodeGen.link(compiled, outputFile, to_obj=to_obj, opt=opt, dev=dev, hotswap=hotswap, debug=debug, includes=includes, linkWith=_linkWith, headerIncludePath=_headerIncludePath, target=target, context=contextCCode, runtimeBuild=compileRuntime) if compileRuntime: saveParser.save(parser, compileRuntime) print("\n======== recompiling =========") print("Compilation took : " + str(time() - time1)) print("") if run: if to_obj: Error.error("Cannot run .obj") CodeGen.exec(outputFile) didCompile = True parser.didCompile = True return parser elif run: CodeGen.exec(outputFile) return declarations fil = filenames sour = sources c = compile(target, sour, fil) return c except (EOFError, ArithmeticError) as e: if dev or _raise: Error.error(str(e)) else: print(e, file=sys.stderr) exit(1) if didCompile: print("Compilation took : " + str(time() - time1))