def static_init_app_ast(self, name): """Generate an APP to call static initializer for class name""" accessAst = Ast('STATIC_ACCESS', [], type_name=name, name=constants.STATIC_INIT, coord=sys_coord()) app_ast = Ast('APP', [accessAst], coord=sys_coord()) return app_ast
def default_constructor_ast(self): return (Ast('DEFN', [ Ast('TYPE', coord=sys_coord(), type_name=self.class_name, rank=0), Ast('PARAMS', [], coord=sys_coord()), Ast('BLOCK', [], coord=sys_coord()) ], name=self.class_name, kind='constructor', isStatic=True, coord=sys_coord()))
def ensure_super(self, ast): assert (ast.tag == 'DEFN' and ast.kind == 'constructor') block = ast.kids[2] needs_super = (len(block.kids) == 0 or block.kids[0].tag != 'APP' or block.kids[0].kids[0].tag != 'ID' or block.kids[0].kids[0].name != 'super') if needs_super: super_call = (Ast('APP', [Ast('ID', [], name='super', coord=sys_coord())], coord=sys_coord())) block.kids.insert(0, super_call) return ast
def make_main(self, splits): code = [self.static_init_app_ast(constants.MAIN_CLASS)] for ast in splits.classes: assert (ast.tag == 'CLASS') code.append(self.static_init_app_ast(ast.type_name)) code += splits.static_decls ret_type = Ast('TYPE', [], type_name='Void', rank=0, coord=sys_coord()) params = Ast('PARAMS', [], coord=sys_coord()) block = Ast('BLOCK', code + splits.stmts, coord=sys_coord()) return Ast('DEFN', [ret_type, params, block], isStatic=True, kind='function', name=constants.MAIN_FN, coord=sys_coord())
def malloc(self): assert (len(self.constr_asts) == 1) constr = self.constr_asts[0] assert (constr.tag == 'DEFN') assert (constr.kind == 'constructor') name = self.class_name constr_params = constr.kids[1] assert (constr_params.tag == 'PARAMS') actuals = [ Ast('ID', name=param.name, coord=sys_coord()) for param in constr_params.kids ] self_ref = Ast('ID', name='self', coord=sys_coord()) access_ast = Ast('ACCESS', [self_ref], coord=sys_coord(), name=self.klass.instance_init_name()) app_ast = Ast('APP', [access_ast] + actuals, coord=sys_coord()) type_id = Ast('TYPE_ID', type_name=name, rank=0, coord=sys_coord()) template = Constructor.MALLOC_BLOCK_TEMPLATE.replace('$C', name) template_dict = { "$typeId": type_id, "$initCall": app_ast, } block = Template.substitute('block', template, template_dict) ret_type = Ast('TYPE', type_name=name, rank=0, coord=sys_coord()) params = copy.deepcopy(constr_params) ast = Ast('DEFN', [ret_type, params, block], name=name, kind='function', isStatic=True, coord=sys_coord()) return ast
def instance_init(self): """return copy of constr_asts[0] with name changed to SELF_INIT and kind set to function """ assert (len(self.constr_asts) == 1) constr = self.constr_asts[0] assert (constr.tag == 'DEFN') assert (constr.kind == 'constructor') init = copy.deepcopy(constr) init.name = self.klass.instance_init_name() init.kind = 'function' init.isStatic = False self_ast = Ast('ID', name='self', coord=sys_coord()) return_ast = Ast('RETURN', [self_ast], coord=sys_coord()) block = init.kids[2] assert (block.tag == 'BLOCK') block.kids.append(return_ast) return init
def xform_super(self, constr): """take super(...) call in constr (by the time it is called, it must have one) and replace it with super.INSTANCE_INIT(...) """ assert (constr.tag == 'DEFN' and constr.kind == 'constructor') super_klass = checker.types.get(self.klass.parent) assert (super_klass) block = constr.kids[2] super_call = block.kids[0] assert (super_call.tag == 'APP') assert (super_call.kids[0].tag == 'ID') assert (super_call.kids[0].name == 'super') if super_klass.name != constants.OBJECT: super_id = Ast('ID', name='super', coord=sys_coord()) super_init_name = super_klass.instance_init_name() access = Ast('ACCESS', [super_id], name=super_init_name, coord=sys_coord()) params = [access] + copy.deepcopy(super_call.kids[1:]) block.kids[0] = Ast('APP', params, coord=sys_coord()) else: block.kids.pop(0) #excise super call as super is Object
def substitute(non_terminal, template, template_dict): """return ast corresponding to the walnut source code template parsed as non_terminal with all occurrences of the $KEY replaced by the precomputed ast from template_dict[KEY] """ #set up artificial source path to indicate caller's location path = str(sys_coord(2)) n_errors, ast = parse_string(path, template, non_terminal, template_dict) if n_errors > 0: sys.stderr.write('INTERNAL ERROR: template parse has %d errors' % n_errors) return ast
def __init__(self, splits): super().__init__(constants.MAIN_CLASS, constants.OBJECT, sys_coord(), splits) main_ast = self.make_main(splits) splits.fns.append(main_ast)
def __init__(self, element_type, rank): super().__init__(element_type, 'Array', sys_coord(), Splits(Ast('CLASS', [])), rank) assert(rank > 0)
def __init__(self): super().__init__(constants.NIL_TYPE, 'nil') self.type = self self.coord = sys_coord()
def __init__(self, name): super().__init__(name, 'primitive') self.type = self self.coord = sys_coord()
from splits import Splits from walnutsys import sys_coord from util import is_multi_def from toptypes import TopTypes from type import NilType, PrimitiveType # top-level of semantic checker which provides behavior # (note that checker simply provides a global variable to # access important data-structures like types, without any # interesting behavior; all behavior is implemented here). PREDEF_CLASSES = [ Ast('CLASS', [], type_name=constants.OBJECT, super_name=None, coord=sys_coord()), #Ast('CLASS', [], type_name='System', super_name=None, coord=sys_coord()), ] PREDEF_TYPES = [ 'Int', 'Real', 'String', 'Void', ] class SemanticChecker: def __init__(self): checker.types = TopTypes() checker.errors = Errors()