import mem:* import str:* import vec:* import set:* import ast_nodes:* import io:* // hmm, like the ast_node, this is another candadate for being fully an ADT // one issue is that there are properties shared between most of the options (indirection, say) adt base_type { none, object, no_type_adt_option, function, template, template_type, void_return, boolean, character, ucharacter, short_int, ushort_int, integer, uinteger, long_int, ulong_int, floating, double_precision } fun type_ptr(): *type { return new()->construct() } fun type_ptr(definition: *ast_node): *type return type_ptr(definition, set()); fun type_ptr(definition: *ast_node, traits: set): *type { return new()->construct(definition, traits) } fun type_ptr(base: base_type): *type return type_ptr(base, 0, false); fun type_ptr(base: base_type, indirection: int): *type return type_ptr(base, indirection, false) fun type_ptr(base: base_type, indirection: int, is_ref: bool): *type { return new()->construct(base, indirection, is_ref) } fun type_ptr(parameters: vec<*type>, return_type: *type, indirection: int, is_ref: bool, is_variadic: bool, is_raw: bool): *type return new()->construct(parameters, return_type, indirection, is_ref, is_variadic, is_raw) fun type_ptr(traits: set): *type { return new()->construct(traits) } obj type (Object) { var base: base_type var parameter_types: vec<*type> var is_variadic: bool var is_raw: bool var return_type: *type var indirection: int var type_def: *ast_node var traits: set var is_ref: bool fun construct(): *type { base.copy_construct(&base_type::none()) parameter_types.construct() indirection = 0 return_type = null() type_def = null() traits.construct() is_ref = false is_variadic = false is_raw = false return this } fun construct(traits_in: set): *type { base.copy_construct(&base_type::template_type()) parameter_types.construct() indirection = 0 return_type = null() type_def = null() traits.copy_construct(&traits_in) is_ref = false is_variadic = false is_raw = false return this } fun construct(base_in: base_type, indirection_in: int, is_ref_in: bool): *type { base.copy_construct(&base_in) parameter_types.construct() indirection = indirection_in return_type = null() type_def = null() traits.construct() is_ref = is_ref_in is_variadic = false is_raw = false return this } fun construct(type_def_in: *ast_node, traits_in: set): *type { base.copy_construct(&base_type::object()) parameter_types.construct() indirection = 0 return_type = null() type_def = type_def_in traits.copy_construct(&traits_in) is_ref = false is_variadic = false is_raw = false return this } fun construct(parameter_types_in: vec<*type>, return_type_in: *type, indirection_in: int, is_ref_in: bool, is_variadic_in: bool, is_raw_in: bool): *type { base.copy_construct(&base_type::function()) parameter_types.copy_construct(¶meter_types_in) return_type = return_type_in indirection = indirection_in type_def = null() traits.construct() is_ref = is_ref_in is_variadic = is_variadic_in is_raw = is_raw_in return this } fun copy_construct(old: *type) { base.copy_construct(&old->base) parameter_types.copy_construct(&old->parameter_types) return_type = old->return_type indirection = old->indirection type_def = old->type_def traits.copy_construct(&old->traits) is_ref = old->is_ref is_variadic = old->is_variadic is_raw = old->is_raw } fun operator=(other: ref type) { destruct() copy_construct(&other) } fun destruct() { base.destruct() parameter_types.destruct() traits.destruct() } fun operator!=(other: ref type):bool return !equality(other, true); fun operator==(other: ref type):bool return equality(other, true); fun equality(other: *type, care_about_ref: bool):bool return equality(*other, care_about_ref); fun equality(other: ref type, care_about_ref: bool):bool { if (parameter_types.size != other.parameter_types.size || is_variadic != other.is_variadic || is_raw != other.is_raw) return false for (var i = 0; i < parameter_types.size; i++;) if (!deref_equality(parameter_types[i], other.parameter_types[i])) return false if (care_about_ref && (is_ref != other.is_ref)) return false return base == other.base && deref_equality(return_type, other.return_type) && indirection == other.indirection && deref_equality(type_def, other.type_def) && traits == other.traits } fun to_string(): str return to_string(true); fun to_string(include_traits: bool): str { var trait_string = str() if (include_traits) { trait_string = str(":[") traits.for_each(fun(t: str) trait_string += t;) trait_string += "] " } var indr_string = str("") if (is_ref) indr_string += " ref " if (is_variadic) indr_string += " variadic " if (is_raw) indr_string += " raw " for (var i = 0; i < indirection; i++;) indr_string += "*" match (base) { base_type::none() return indr_string + str("none") + trait_string base_type::object() return indr_string + get_ast_name(type_def) + trait_string base_type::no_type_adt_option() return indr_string + "no_type_adt_option" + trait_string base_type::template() return indr_string + str("template") + trait_string base_type::template_type() return indr_string + str("template_type") + trait_string base_type::void_return() return indr_string + str("void_return") + trait_string base_type::boolean() return indr_string + str("boolean") + trait_string base_type::character() return indr_string + str("character") + trait_string base_type::short_int() return indr_string + str("short") + trait_string base_type::integer() return indr_string + str("integer") + trait_string base_type::long_int() return indr_string + str("long") + trait_string base_type::ucharacter() return indr_string + str("ucharacter") + trait_string base_type::ushort_int() return indr_string + str("ushort") + trait_string base_type::uinteger() return indr_string + str("uinteger") + trait_string base_type::ulong_int() return indr_string + str("ulong") + trait_string base_type::floating() return indr_string + str("floating") + trait_string base_type::double_precision() return indr_string + str("double_precision") + trait_string base_type::function() { var temp = indr_string + str("fun(") parameter_types.for_each(fun(parameter_type: *type) temp += parameter_type->to_string() + ", ";) return temp + ")" + return_type->to_string() + trait_string } } return str("impossible type, indirection:") + indirection } fun rank(): int { if (indirection > 0) return 5 match (base) { base_type::character() return 1 base_type::ucharacter() return 1 base_type::short_int() return 2 base_type::ushort_int() return 2 base_type::integer() return 3 base_type::uinteger() return 3 base_type::long_int() return 4 base_type::ulong_int() return 4 base_type::floating() return 5 base_type::double_precision() return 6 } return 0 } fun clone(): *type return clone_with_indirection(indirection, is_ref); fun clone_without_ref(): *type return clone_with_indirection(indirection, false); fun clone_with_ref(): *type return clone_with_indirection(indirection, true); fun clone_with_increased_indirection(): *type return clone_with_indirection(indirection+1); fun clone_with_increased_indirection(more: int, is_ref_in: bool): *type return clone_with_indirection(indirection+more, is_ref_in); fun clone_with_decreased_indirection(): *type return clone_with_indirection(indirection-1); fun clone_with_indirection(ind: int): *type return clone_with_indirection(ind, false) fun clone_with_indirection(ind: int, is_ref_in: bool): *type { var to_ret = new() to_ret->copy_construct(this) to_ret->indirection = ind to_ret->is_ref = is_ref_in return to_ret } fun is_object(): bool { match (base) { base_type::object() return true } return false } fun is_bool(): bool { match (base) { base_type::boolean() return true } return false } fun is_function(): bool { match (base) { base_type::function() return true } return false } fun is_void(): bool { match (base) { base_type::void_return() return true } return false } fun is_empty_adt_option(): bool { match (base) { base_type::no_type_adt_option() return true } return false } fun is_none(): bool { match (base) { base_type::none() return true } return false } fun is_template_type(): bool { match (base) { base_type::template_type() return true } return false } fun is_signed_type(): bool { match (base) { base_type::character() return true base_type::short_int() return true base_type::integer() return true base_type::long_int() return true base_type::ucharacter() return false base_type::ushort_int() return false base_type::uinteger() return false base_type::ulong_int() return false } return false } }