def visit_Function(self, obj: Function): body = [] for i in range(obj.temp_count): body.append(cgen.Declare(AIZE_OBJECT_REF, f"AT{i}", None)) if obj.unique != 'main': body.append( cgen.ExprStmt(cgen.Call(cgen.GetVar("aize_mem_enter"), []))) self.in_main_main = False else: body.append( cgen.ExprStmt(cgen.Call(cgen.GetVar("aize_mem_init"), []))) self.in_main_main = True for stmt in obj.body: ret = self.visit(stmt) if self.debug: body.append(cgen.Comment(f"{stmt}")) body.append(cgen.printf(str(stmt))) if isinstance(ret, (list, tuple)): body.extend(ret) elif ret is not None: body.append(ret) if len(obj.body) == 0 or not isinstance(obj.body[-1], Return): body.append( cgen.ExprStmt(cgen.Call(cgen.GetVar("aize_mem_exit"), []))) return cgen.Function( obj.unique, {param.unique: self.visit(param.type) for param in obj.args}, self.visit(obj.type.ret), body)
def visit_Class(self, obj: Class): cls_ptr = self.visit(obj.type) attrs = {'ATBASE': AIZE_BASE} attrs.update({ attr.unique: self.visit(attr.type) for attr in obj.attrs.values() }) cls_struct = cgen.Struct(obj.unique, attrs) implementers = {} owned_methods = [] methods = {} for n, meth_proto in enumerate(obj.methods.values()): meth = obj.type.get_method(meth_proto.name) if meth.owner is obj.type: methods[str(len(owned_methods))] = cgen.Ref( cgen.GetVar(meth.unique)) owned_methods.append(meth_proto) implementers[obj.type.unique.upper()] = cgen.ArrayInit(methods) ttable = cgen.GlobalArray( obj.type.ttable, cgen.void_ptr(), (len(self.program.classes), len(owned_methods)), cgen.ArrayInit(implementers)) new_unique = obj.type.cls_namespace.get_name("new").unique new_attrs = { attr.unique: self.visit(attr.type) for attr in obj.attrs.values() } def set_attr(attr): return cgen.ExprStmt( cgen.SetArrow(self.get_cls_ptr(cgen.GetVar('mem'), obj.type), attr.unique, cgen.GetVar(attr.unique))) new_func = cgen.Function(new_unique, new_attrs, cls_ptr, [ cgen.ExprStmt(cgen.Call(cgen.GetVar("aize_mem_enter"), [])), cgen.Declare( cls_ptr, "mem", cgen.StructInit([ cgen.Call(cgen.GetVar("aize_mem_malloc"), [cgen.SizeOf(cls_struct.struct_type)]), cgen.GetVar(cls_struct.name.upper()) ])), *(set_attr(attr) for attr in obj.attrs.values()), cgen.ExprStmt( cgen.SetArrow(cgen.GetAttr(cgen.GetVar('mem'), 'obj'), "ref_count", cgen.Constant(0))), cgen.Return( cgen.Call(cgen.GetVar('aize_mem_ret'), [cgen.GetVar("mem")])), ]) methods = [] for meth in obj.methods.values(): methods.append(self.visit(meth)) return [cls_struct, new_func, *methods, ttable]
def visit_Return(self, obj: Return): if self.in_main_main: return cgen.Return(self.visit(obj.val)) val = self.visit(obj.val) if isinstance(obj.val.ret, ClassType): ret = cgen.Call(cgen.GetVar("aize_mem_ret"), [val]) return cgen.Return(ret) else: ret = cgen.Declare(self.visit(obj.val.ret), 'ATR', val) exit_call = cgen.ExprStmt( cgen.Call(cgen.GetVar("aize_mem_exit"), [])) return [ret, exit_call, cgen.Return(cgen.GetVar('ATR'))]
def visit_Call(self, obj: Call): if obj.method_data is not None: args = obj.args obj = obj.method_data ttable = obj.pointed.owner.ttable left = cgen.StrExpr( f"{ttable}[(AT{obj.depth} = {self.visit(obj.obj)}).typeid][{obj.index}]" ) left = cgen.Cast(left, self.visit(obj.pointed.type)) left = cgen.Call(left, [cgen.GetVar(f"AT{obj.depth}")] + [self.visit(arg) for arg in args]) return left return cgen.Call(self.visit(obj.left), [self.visit(arg) for arg in obj.args])