def import_vars(self, module_exports: dict, lfp): for name, ve in module_exports.items(): if self._inner_get(name) is None: self.vars[name] = ve else: raise errs.TplEnvironmentError( "Name '{}' already defined. ".format(name), lfp)
def get_type_and_ptr_def(self, param_types: list, lf) -> (CallableType, int): t_addr = self.poly.get_entry_by(param_types, func_eq_params) if t_addr is None: raise errs.TplEnvironmentError( f"Cannot resolve param {param_types}. ", lf) return t_addr
def define_const_set(self, name: str, type_: typ.Type, addr: int, lfp: tl.LineFilePos): if self._inner_get(name) is not None: raise errs.TplEnvironmentError( "Name '{}' already defined. ".format(name), lfp) entry = VarEntry(type_, addr, True) self.vars[name] = entry
def get_type(self, name, lfp) -> typ.Type: if name in typ.PRIMITIVE_TYPES: return typ.PRIMITIVE_TYPES[name] entry = self._inner_get(name) if entry is None: raise errs.TplEnvironmentError( f"Name '{name}' is not defined in this scope. ", lfp) return entry.type
def is_named_function(self, name: str, lfp) -> bool: entry = self._inner_get(name) if entry is None: raise errs.TplEnvironmentError( f"Name '{name}' is not defined in this scope. ", lfp) if isinstance(entry, FunctionEntry): return entry.named return False
def _find_method(self, name, arg_types, lf): if name in self.methods: poly: util.NaiveDict = self.methods[name] return find_closet_func(poly, arg_types, name, True, lambda poly_d, i: poly_d.values[i][2], lf)[1] raise errs.TplEnvironmentError( f"Class {self.name} does not have method '{name}'. ", lf)
def define_function(self, name: str, func_type: typ.CallableType, fn_ptr: int, lfp: tl.LineFilePos): old_entry = self._inner_get(name) if old_entry is not None: if isinstance(old_entry, FunctionEntry): old_entry.placer.add_poly(func_type, fn_ptr) return raise errs.TplEnvironmentError( "Name '{}' already defined. ".format(name), lfp) placer = typ.FunctionPlacer(func_type, fn_ptr) entry = FunctionEntry(placer, const=True, named=True) self.vars[name] = entry
def find_field(self, name: str, lf) -> (int, Type, Type, bool, int): """ Returns (field_pos, type, defined_class, const, permission) :param name: :param lf: :return: """ for mro_t in self.mro: if name in mro_t.fields: return mro_t.fields[name] raise errs.TplEnvironmentError( f"Class {self.name} does not have field '{name}'. ", lf)
def vars_subset(self, names: dict, lfp) -> dict: """ :param names: dict of {real name in scope: export name} :param lfp: :return: """ sub = {} for name, export_name in names.items(): entry = self._inner_get(name) if entry is None: raise errs.TplEnvironmentError( "Name '{}' is not defined in this scope. ".format(name), lfp) sub[export_name] = entry return sub
def find_local_method(self, name: str, arg_types: list, lf) -> (int, int, MethodType): """ Returns only the matching method that is defined in this class, not in superclasses. The mechanism is that, for example, the signature of 'hash' defined in 'Object' is 'hash(this: *Object) int', but in 'String' is 'hash(this: *String) int'. Checking the param type of 'this' should determine the method's definition class. :param name: :param arg_types: :param lf: :return: """ method_id, method_ptr, method_t = self._find_method( name, arg_types, lf) def_this_t = method_t.param_types[0].base if isinstance(def_this_t, GenericClassType): def_this_t = def_this_t.base if def_this_t != self: raise errs.TplEnvironmentError( f"Cannot resolve local method {name}{arg_types[1:]}. ", lf) return method_id, method_ptr, method_t
def define_template(self, gen: typ.Generic, lfp: tl.LineFilePos): if gen.full_name() in self.templates: raise errs.TplEnvironmentError( f"Template '{gen.full_name()}' already defined. ", lfp) self.templates[gen.full_name()] = VarEntry(gen, -1, True)
def get_method_type(self, name, lfp): if name in self.temp_methods: return self.temp_methods[name].type raise errs.TplEnvironmentError( "Method '{}' already defined. ".format(name), lfp)
def set_exports(self, exports: dict, lfp): if self.exports is None: self.exports = exports else: raise errs.TplEnvironmentError("Multiple exports in one module. ", lfp)
def continue_label(self) -> str: raise errs.TplEnvironmentError()
def fallthrough(self) -> str: if self.fallthrough_label is None: raise errs.TplEnvironmentError( "Default case or case expression cannot have 'fallthrough'. ") return self.fallthrough_label
def validate_rtype(self, actual_rtype: typ.Type, lfp: tl.LineFilePos): raise errs.TplEnvironmentError("Return outside function. ", lfp)
def fallthrough(self): raise errs.TplEnvironmentError("Fallthrough outside switch-case")
def is_const(self, name: str, lfp) -> bool: entry = self._inner_get(name) if entry is None: raise errs.TplEnvironmentError( f"Name '{name}' is not defined in this scope. ", lfp) return entry.const
def break_label(self) -> str: raise errs.TplEnvironmentError()
def get(self, name, lfp) -> int: entry = self._inner_get(name) if entry is None: raise errs.TplEnvironmentError( f"Name '{name}' is not defined in this scope. ", lfp) return entry.addr
def add_poly(self, type_: CallableType, addr: int): if type_ in self.poly: raise errs.TplEnvironmentError("Function already defined.") self.poly[type_] = addr