summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp105
1 files changed, 99 insertions, 6 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 878fef85..25be3d8a 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -79,6 +79,8 @@ struct Context
void pop_traits(const t_trait_list& list);
};
+//static void fix_param_count(const Span& sp, Context& context, const ::HIR::Path& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params);
+static void fix_param_count(const Span& sp, Context& context, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params);
class ExprVisitor_Enum:
public ::HIR::ExprVisitor
@@ -128,7 +130,7 @@ public:
{
TRACE_FUNCTION_F("loop { ... }");
- // TODO: Node must return ()?
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
node.m_code->visit( *this );
}
@@ -337,7 +339,9 @@ public:
{
TRACE_FUNCTION_F("... as " << node.m_res_type);
this->context.add_ivars( node.m_value->m_res_type );
- // Depending on the form of the result type, it can lead to links between the input and output
+
+ // TODO: Depending on the form of the result type, it can lead to links between the input and output
+
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_Unsize& node) override
@@ -366,6 +370,53 @@ public:
node.m_value->visit( *this );
}
+
+ void add_ivars_generic_path(const Span& sp, ::HIR::GenericPath& gp) {
+ for(auto& ty : gp.m_params.m_types)
+ this->context.add_ivars(ty);
+ }
+ void add_ivars_path(const Span& sp, ::HIR::Path& path) {
+ TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
+ (Generic,
+ this->add_ivars_generic_path(sp, e);
+ ),
+ (UfcsKnown,
+ this->context.add_ivars(*e.type);
+ this->add_ivars_generic_path(sp, e.trait);
+ for(auto& ty : e.params.m_types)
+ this->context.add_ivars(ty);
+ ),
+ (UfcsUnknown,
+ TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
+ ),
+ (UfcsInherent,
+ this->context.add_ivars(*e.type);
+ for(auto& ty : e.params.m_types)
+ this->context.add_ivars(ty);
+ )
+ )
+ }
+
+ ::HIR::TypeRef get_structenum_ty(const Span& sp, bool is_struct, ::HIR::GenericPath& gp)
+ {
+ if( is_struct )
+ {
+ const auto& str = this->context.m_crate.get_struct_by_path(sp, gp.m_path);
+ fix_param_count(sp, this->context, gp, str.m_params, gp.m_params);
+
+ return ::HIR::TypeRef::new_path( gp.clone(), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) );
+ }
+ else
+ {
+ auto s_path = gp.m_path;
+ s_path.m_components.pop_back();
+
+ const auto& enm = this->context.m_crate.get_enum_by_path(sp, s_path);
+ fix_param_count(sp, this->context, gp, enm.m_params, gp.m_params);
+
+ return ::HIR::TypeRef::new_path( ::HIR::GenericPath(mv$(s_path), gp.m_params.clone()), ::HIR::TypeRef::TypePathBinding::make_Enum(&enm) );
+ }
+ }
void visit(::HIR::ExprNode_TupleVariant& node) override
{
@@ -374,8 +425,10 @@ public:
this->context.add_ivars( val->m_res_type );
}
- // TODO: Result type
- // TODO: Bind fields with type params
+ // - Create ivars in path, and set result type
+ const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+ // TODO: Bind fields with type params (coercable)
for( auto& val : node.m_args ) {
val->visit( *this );
@@ -388,8 +441,10 @@ public:
this->context.add_ivars( val.second->m_res_type );
}
- // TODO: Result type
- // TODO: Bind fields with type params
+ // - Create ivars in path, and set result type
+ const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+ // TODO: Bind fields with type params (coercable)
for( auto& val : node.m_values ) {
val.second->visit( *this );
@@ -583,3 +638,41 @@ void Context::pop_traits(const t_trait_list& list) {
void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, const ::std::vector< ::HIR::TypeRef>& ty_args, const ::HIR::TypeRef& impl_ty, const char *name)
{
}
+
+template<typename T>
+void fix_param_count_(const Span& sp, Context& context, const T& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params)
+{
+ if( params.m_types.size() == param_defs.m_types.size() ) {
+ // Nothing to do, all good
+ return ;
+ }
+
+ if( params.m_types.size() == 0 ) {
+ for(const auto& typ : param_defs.m_types) {
+ (void)typ;
+ params.m_types.push_back( ::HIR::TypeRef() );
+ context.add_ivars( params.m_types.back() );
+ }
+ }
+ else if( params.m_types.size() > param_defs.m_types.size() ) {
+ ERROR(sp, E0000, "Too many type parameters passed to " << path);
+ }
+ else {
+ while( params.m_types.size() < param_defs.m_types.size() ) {
+ const auto& typ = param_defs.m_types[params.m_types.size()];
+ if( typ.m_default.m_data.is_Infer() ) {
+ ERROR(sp, E0000, "Omitted type parameter with no default in " << path);
+ }
+ else {
+ // TODO: What if this contains a generic param? (is that valid? Self maybe, what about others?)
+ params.m_types.push_back( typ.m_default.clone() );
+ }
+ }
+ }
+}
+//void fix_param_count(const Span& sp, Context& context, const ::HIR::Path& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params) {
+// fix_param_count_(sp, context, path, param_defs, params);
+//}
+void fix_param_count(const Span& sp, Context& context, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params) {
+ fix_param_count_(sp, context, path, param_defs, params);
+}