def compileToC(self, codegen): self.typ.toCType() #if self.typ.package == "_global" and type(self.typ) in [Types.Struct, Types.Enum]: # codegen.append("NULL") # return package = self.typ.package if self.typ.package != "" else "_global" fullName = SimplifyAst.toUniqueID(package, self.typ.normalName, self.typ.remainingGen) if not type(self.typ) in [Types.Interface, Types.Pointer, Types.Alias, Types.Null]: if type(self.typ) is Types.T: typeof_none = Typeof(self, Types.Null()) Tree.castFrom(typeof_none.type, Parser.IType, typeof_none, "", codegen) else: codegen.append(f"{fullName}_get_type(NULL," + codegen.getContext() + ")") else: if type(self.typ) is Types.Pointer: codegen.append("_global_boxPointerType(_global_PointerTypeInit(") tmp = Typeof(self, self.typ.pType) Cast.castFrom(tmp.type, Parser.IType, tmp, "", codegen) codegen.append(",0)," + codegen.getContext() + ")") elif type(self.typ) is Types.Null: codegen.append(f"&None_Type") else: codegen.append(f"&{fullName}_Type")
def replaceT(self, structT, newName): self.package = structT.package self.normalName = newName self.const = structT.const self.onlyGenericName = SimplifyAst.toUniqueID("", "", structT.remainingGen)[1:] self.generic = structT.remainingGen self.replaced = True self.realNormalName = structT.normalName self.type = structT
def getFieldOfInterface(iType, pointer=False): n = SimplifyAst.sanitize(iType.name) codegen.append(f"*{n}_{self.field}") if pointer: codegen.append("(") else: codegen.append("ByValue(") self.nodes[0].compileToC(codegen) if pointer: codegen.append(")") codegen.append(")")
def funcBody(parser, name, names, types, brace, returnType, do): body = Tree.FuncBody(parser) body.name = name body.returnType = returnType body.package = parser.package body.do = do body.types = types brace.body = body parser.currentNode.addNode(body) parser.currentNode = body if not parser.sc and not SimplifyAst.isGenericFunc(brace): body.sc = False if parser.nextToken().token == "\n": Parser.callToken(parser) while not Parser.isEnd(parser): if parser.nextToken().token == "\n": Parser.callToken(parser) parser.currentNode = body.owner Scope.decrScope(parser) #print("should not compile", name) return body for i in range(len(names)): n = Tree.InitArg(names[i], parser) n.package = parser.package n.varType = types[i] n.imutable = not Scope.isMutable(parser, parser.package, names[i]) body.addNode(n) parser.nextToken() Parser.callToken(parser) #incase next case is newline while not Parser.isEnd(parser): parser.nextToken() t = parser.thisToken().token Parser.callToken(parser) ExprParser.endExpr(parser) parser.currentNode = body.owner Scope.decrScope(parser) return body
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 castFrom(originalType, newType, node, realName, codegen): key_cast = (originalType.name, newType.name) if originalType == newType: node.compileToC(codegen) return if originalType.isType(Types.FuncPointer): return node.compileToC(codegen) #elif type(newType) is Types.I32: # return node.compileToC(codegen) elif type(newType) is Types.Interface: n = SimplifyAst.sanitize(newType.name if newType.package != "_global" else "_global_" + newType.name) if not key_cast in casted: from TopCompiler import topc tmp = SimplifyAst.sanitize(originalType.name + "_VTABLE_FOR_" + newType.name) #CodeGen.genGlobalTmp(codegen.filename) codegen.inFunction() codegen.append("struct " + n + "_VTABLE " + tmp + ";") codegen.outFunction() else: tmp = casted[key_cast] if not type(originalType) is Types.Pointer: node.error("Can only convert to interface from pointer") originalType = originalType.pType codegen.append(n + "FromStruct(") node.compileToC(codegen) codegen.append(",") codegen.append("&" + tmp) codegen.append(",") if not key_cast in casted: get_type = BasicTypes.Typeof(node, originalType) casted[key_cast] = tmp castFrom(get_type.type, Parser.IType, get_type, "", codegen) else: codegen.append(tmp + ".type") for field in newType.types: #@cleanup handle recursive cast codegen.append(f", offsetof({originalType.toCType()},{field})") for field in newType.methods: if field in realName: name = realName[field] else: pack = "_global" if originalType.package == "" else originalType.package name = f"{pack}_{originalType.normalName}_{field}" codegen.append(f", &{name}") codegen.append(")") return elif type(newType) is Types.Array: if type(originalType) is Types.Alias: node.compileToC(codegen) return if newType.both and originalType.isType(Types.Pointer) and originalType.pType.static: if key_cast in casted: funcName = casted[key_cast] else: funcName = CodeGen.genGlobalTmp(codegen.filename) codegen.inGenerateFunction() inputT = codegen.getName() typNewC = newType.toCType() initCall = typNewC.replace("struct ", "") + "Init" codegen.append(f"{typNewC} {funcName}({originalType.toCType()} {inputT}) {{\n") codegen.append(f"return {initCall}({inputT}->data, {originalType.pType.numElements});") codegen.append("};\n") codegen.outFunction() casted[key_cast] = funcName codegen.append(f"{funcName}(") node.compileToC(codegen) codegen.append(")") return elif newType.both and originalType.empty: initCall = newType.toCType().replace("struct ", "") + "Init" codegen.append(initCall + "(NULL, 0)") return elif newType.both and not originalType.both and not originalType.static: if not type(node) in [Tree.ReadVar, Tree.Field]: node.error("not handled yet") typNewC = newType.toCType() initCall = typNewC.replace("struct ", "") + "Init" codegen.append(f"{initCall}(") node.compileToC(codegen) codegen.append(".data, ") node.compileToC(codegen) codegen.append(".length)") return elif originalType.empty: structName = newType.toCType()[len("struct "):] codegen.append(structName + "Init(0, 0, NULL, NULL)") """ print(structName) if key_cast in casted: funcName = casted[key_cast] else: funcName = CodeGen.genGlobalTmp(codegen.filename) codegen.inGenerateFunction() inputT = codegen.getName() typNewC = newType.toCType() codegen.append(f"{typNewC} {funcName}({originalType.toCType()} {inputT}) {{\n") codegen.append(f"return *(({typNewC}*) &{inputT});") codegen.append("};\n") codegen.outFunction() casted[key_cast] = funcName codegen.append(f"{funcName}(") node.compileToC(codegen) codegen.append(")") """ return print(newType.name) print(originalType.name) node.error("not handled yet") elif type(newType) in [Types.Enum, Types.Struct] and notSpecified(originalType): if Types.isMaybe(newType): codegen.append("NULL") return funcName = CodeGen.genGlobalTmp(codegen.filename) tmp = codegen.getName() inputT = codegen.getName() codegen.inGenerateFunction() typNewC = newType.toCType() codegen.append(f"static inline {typNewC} {funcName}({originalType.toCType()} {inputT}) {{\n") codegen.append(f"{typNewC} {tmp};") if type(newType) is Types.Enum: #@cleanup maybe optimization will cause this not to be valid codegen.append(f"{tmp}.tag = {inputT}.tag;") unionTyp = typNewC.replace("struct", "union", 1) + "_cases" codegen.append(f"{tmp}.cases = *({unionTyp}*) &({inputT}.cases);") else: for field in newType.types: #change this when using comes out codegen.append(f"{tmp}.{field} = {inputT}.{field};") codegen.append(f"return {tmp};\n}}\n") codegen.outFunction() codegen.append(funcName + "(") node.compileToC(codegen) codegen.append(")") return codegen.append("(" + newType.toCType() + ")") node.compileToC(codegen)
def compileToC(self, codegen): codegen.inFunction() iType = self.iType context = codegen.getName() methods = {} pNone = Types.Pointer(Types.Null(), True) for methName in iType.methods: meth = iType.methods[methName] f = Types.FuncPointer([pNone] + meth.args, meth.returnType, meth.generic, meth.do) methods[methName] = f #interface as c struct vtable_name = self.name + "_VTABLE" codegen.append("struct " + self.name + " {\n") codegen.append(f"struct {vtable_name}* vtable;\n") codegen.append("void* data;\n") codegen.append("};") type_interface = "struct _global_Type" def gen_func(meth, field): s = meth.returnType.toCType() s += f"(*{field})(" for (iter, i) in enumerate(meth.args): s += i.toCType() + "," s += "struct _global_Context*" s += ")" return s codegen.append(f"struct {vtable_name} {{") codegen.append(f"{type_interface} type;") for field in methods: meth = methods[field] meth_name = "method_" + field codegen.append(f"{gen_func(meth, meth_name)};\n") #codegen.append(f"{methods[field].toCType()} method_{field};\n") codegen.append("};") type_interface = Parser.IType.toCType() #for field in iType.types: # codegen.append(f"unsigned short field_{field};\n") #just store offset, should be long enough let's see #helper function from struct to interface #if self.iType.package == "" or self.iType.package == "_global": # front = self.normalName #else: front = SimplifyAst.sanitize(self.iType.fullName) if self.iType.package == "" or self.iType.package == "_global": front = "_global_" + front if len(self.iType.remainingGen) > 0: back = "_" + SimplifyAst.sanitize(self.iType.name) else: back = "" codegen.append( f"static inline struct {self.name} {self.name}FromStruct(void* data, struct {vtable_name}* vtable, {type_interface} typ" ) method_names = [] for field in methods: n = codegen.getName() codegen.append(f", {gen_func(methods[field], n)}") method_names.append(n) codegen.append("){ \n") tmp = codegen.getName() codegen.append(f"struct {self.name} {tmp};\n") codegen.append(f"{tmp}.data = data;") codegen.append(f"{tmp}.vtable = vtable;") for (name, field) in zip(method_names, methods): codegen.append(f"{tmp}.vtable->method_{field} = {name};\n") codegen.append(f"{tmp}.vtable->type = typ;\n") codegen.append(f"return {tmp}; \n}}") codegen.append( f"void* {self.name}_get_pointer_to_data(struct {self.name}* self, struct _global_Context* context) {{ return self->data; }}" ) #print() #helper function to call methods for field in methods: typ = methods[field] #print(f"{front}_{field}{back}") codegen.append( f"static inline {typ.returnType.toCType()} {front}_{field}{back}(struct {self.name}* {tmp}" ) names = [] for i in typ.args[1:]: n = codegen.getName() names.append(n) codegen.append(f",{i.toCType()} {n}") codegen.append(f",struct _global_Context* {context}") codegen.append(f"){{\n") codegen.append(f"return {tmp}->vtable->method_{field}({tmp}->data") for i in names: codegen.append(f",{i}") codegen.append(f",{context}") codegen.append(");") codegen.append("\n};") codegen.append( f"static inline {typ.returnType.toCType()} {front}_{field}{back}ByValue(struct {self.name} {tmp}" ) for (iter, i) in enumerate(typ.args[1:]): codegen.append(f",{i.toCType()} {names[iter]}") codegen.append(f",struct _global_Context* {context}") codegen.append(f"){{\n") data = codegen.getName() codegen.append(f"return {tmp}.vtable->method_{field}({tmp}.data") for i in names: codegen.append(f",{i}") codegen.append(f",{context}") codegen.append(");") codegen.append("\n};") codegen.append( f"{type_interface} {self.name}_get_type(struct {self.name}* {tmp}, struct _global_Context* context)" ) codegen.append("{ return " + tmp + "->vtable->type; }") codegen.append( f"{type_interface} {self.name}_get_typeByValue(struct {self.name} {tmp}, struct _global_Context* context)" ) codegen.append("{ return " + tmp + ".vtable->type; }\n") interface_type = Parser.InterfaceType.toCType() if self.name.endswith("_"): typ_name = self.name + "Type" else: typ_name = f"{self.name}_Type" codegen.append(f"{interface_type} {typ_name};") codegen.outFunction() def as_string(s): return f'_global_StringInit({len(s)}, "{s}")' codegen.append(f"{typ_name}.name = " + as_string(iType.normalName)) codegen.append(f";{typ_name}.package = " + as_string(iType.package) + ";") """ struct Animal Animal_FromString(void* data, size_t offset) struct Animal a; a.data = data; a.type = type; a.offset = offset; }; """ if self.name in Types.compiledTypes and not self.name == "_global_Type": del Types.compiledTypes[self.name]