]> Nishi Git Mirror - gwion.git/commitdiff
:art: Introduce ufcc
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 9 Mar 2021 13:08:32 +0000 (14:08 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 9 Mar 2021 13:08:32 +0000 (14:08 +0100)
include/tmp_resolve.h
include/traverse.h
src/lib/object_op.c
src/parse/check.c
src/parse/func_resolve_tmpl.c
tests/ufcc/has_func.gw [new file with mode: 0644]
tests/ufcc/no_func.gw [new file with mode: 0644]

index 6577be04a9d41335650b4966a18b292c9145b85d..fd0bde35f379ede16c482a1689c091c2b2cdc58c 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef __TMPL_RESOLVE
 #define __TMPL_RESOLVE
-ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp);
-ANN2(1, 2) Func find_func_match(const Env env, const Func up, const Exp exp);
+ANN Func find_template_match(const Env env, const Value value, Exp_Call *const exp);
+ANN Func find_func_match(const Env env, const Func up, Exp_Call *const exp);
 #endif
index 5ab16b324cd3bb102e6a03f0b8a4ceb1c21956d7..7c841d0cb53b8b78e160a077ac73226a6f4cb78c 100644 (file)
@@ -47,5 +47,5 @@ ANN m_bool scan1_class_def(const Env, const Class_Def);
 ANN m_bool scan2_class_def(const Env, const Class_Def);
 ANN m_bool check_class_def(const Env, const Class_Def);
 
-ANN Type check_exp_call1(const Env env, const Exp_Call *exp);
+ANN Type check_exp_call1(const Env env, Exp_Call *const exp);
 #endif
index 8b90f6d5d649a972014f9aac3e6e8a2846e6d7c9..3cbc35b4c6bb7bac6a8858f51120f36d86344af9 100644 (file)
@@ -111,8 +111,8 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
         exp_setvar(member->base, 1);
         emit_exp(emit, member->base);
       }
-    const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
-    func_i->m_val = (m_uint)f->code ?: (m_uint)f;
+      const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
+      func_i->m_val = (m_uint)f->code ?: (m_uint)f;
       return;
     }
     const Instr instr = emit_add_instr(emit, DotFunc);
@@ -168,6 +168,9 @@ OP_CHECK(opck_object_dot) {
           _("keyword 'this' must be associated with object instance..."))
   const Value value = get_value(env, member, the_base);
   if(!value) {
+    const Value v = nspc_lookup_value1(env->curr, member->xid);
+    if(v && isa(v->type, env->gwion->type[et_function]) > 0)
+      return v->type;
     env_err(env, exp_self(member)->pos,
           _("class '%s' has no member '%s'"), the_base->name, str);
     if(member->base->type->nspc)
index 24d145d74c79f9009443702d7c48ed19f91a7fe4..ed8a3eb8cd48bcd0381530faff50dad05d01aa9c 100644 (file)
@@ -454,15 +454,40 @@ ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp
   return NULL;
 }
 
-ANN2(1, 2) Func find_func_match(const Env env, const Func up, const Exp exp) {
+ANN static Type check_exp_call(const Env env, Exp_Call* exp);
+
+ANN static Func call2ufcc(const Env env, Exp_Call* call, const Value v) {
+  const Exp this = call->func->d.exp_dot.base;
+  this->next = call->args;
+  call->args = this;
+  call->func->type = v->type;
+  call->func->d.prim.value = v;
+  call->func->d.prim.d.var = call->func->d.exp_dot.xid;
+  call->func->exp_type = ae_exp_primary;
+  call->func->d.prim.prim_type = ae_prim_id;
+  call->args = this;
+  CHECK_OO(check_exp_call(env, call))
+  return call->func->type->info->func;
+}
+
+ANN Func ufcc(const Env env, const Func up, Exp_Call *const call) {
+  const Value v = nspc_lookup_value1(env->curr, up->def->base->xid);
+  if(v && isa(v->type, env->gwion->type[et_function]) > 0 && !vflag(v, vflag_member))
+    return call2ufcc(env, call, v);
+  return NULL;
+}
+
+ANN Func find_func_match(const Env env, const Func up, Exp_Call *const call) {
   Func func;
+  const Exp exp = call->args;
   const Exp args = (exp && isa(exp->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
   if((func = find_func_match_actual(env, up, args, 0, 1)) ||
      (func = find_func_match_actual(env, up, args, 1, 1)) ||
      (func = find_func_match_actual(env, up, args, 0, 0)) ||
      (func = find_func_match_actual(env, up, args, 1, 0)))
     return func;
-  return NULL;
+  return call->func->exp_type == ae_exp_dot && up->value_ref->from->owner_class ?
+    ufcc(env, up, call) : NULL;
 }
 
 ANN m_bool check_traverse_fdef(const Env env, const Func_Def fdef) {
@@ -542,7 +567,7 @@ ANN static m_uint get_type_number(ID_List list) {
   return type_number;
 }
 
-ANN static Func get_template_func(const Env env, const Exp_Call* func, const Value v) {
+ANN static Func get_template_func(const Env env, Exp_Call *const func, const Value v) {
   const Func f = find_template_match(env, v, func);
   if(f) {
 // copy that tmpl->call?
@@ -651,14 +676,22 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
   return ret > 0 ? l->def->base->ret_type : NULL;
 }
 
-ANN m_bool func_check(const Env env, const Exp_Call *exp) {
+ANN m_bool func_check(const Env env, Exp_Call *const exp) {
   CHECK_OB(check_exp(env, exp->func))
   if(exp->func->exp_type == ae_exp_decl)
     ERR_B(exp->func->pos, _("Can't call late function pointer at declaration site"))
   const Type t = actual_type(env->gwion, exp->func->type);
+  if(isa(t, env->gwion->type[et_function]) > 0 &&
+        exp->func->exp_type == ae_exp_dot && !t->info->owner_class) {
+    if(exp->args)
+      CHECK_OB(check_exp(env, exp->args))
+    const Func f = call2ufcc(env, exp, t->info->func->value_ref);
+    if(f)
+      return GW_OK;
+  }
   const Exp e = exp_self(exp);
   struct Op_Import opi = { .op=insert_symbol("@func_check"),
-  .rhs=t, .pos=e->pos, .data=(uintptr_t)e };
+    .rhs=t, .pos=e->pos, .data=(uintptr_t)e };
   CHECK_NB(op_check(env, &opi)) // doesn't really return NULL
   if(e->exp_type != ae_exp_call)
     return 0;
@@ -666,7 +699,7 @@ ANN m_bool func_check(const Env env, const Exp_Call *exp) {
     GW_OK : GW_ERROR;
 }
 
-ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
+ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
   DECL_BO(const m_bool, ret, = func_check(env, exp))
   if(!ret)
     return exp_self(exp)->type;
@@ -688,7 +721,7 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
     CHECK_OO(check_exp(env, exp->args))
   if(tflag(t, tflag_ftmpl))
     return check_exp_call_template(env, (Exp_Call*)exp);
-  const Func func = find_func_match(env, t->info->func, exp->args);
+  const Func func = find_func_match(env, t->info->func, exp);
   if(func) {
     exp->func->type = func->value_ref->type;
     return func->def->base->ret_type;
@@ -838,12 +871,14 @@ DECL_EXP_FUNC(check, Type, Env)
 
 ANN Type check_exp(const Env env, const Exp exp) {
   Exp curr = exp;
-  do {
-    CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
-    if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
-        !fflag(curr->type->info->func, fflag_pure))
-      unset_fflag(env->func, fflag_pure);
-  } while((curr = curr->next));
+  if(!exp->type) {
+    do {
+      CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
+      if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
+          !fflag(curr->type->info->func, fflag_pure))
+        unset_fflag(env->func, fflag_pure);
+    } while((curr = curr->next));
+  }
   return exp->type;
 }
 
index e46fd87a88cf16dadb9578b542e65aefd22c561e..d75db3b192b4a3fe1cd58cc70f0d2dee9c46c880 100644 (file)
@@ -16,7 +16,7 @@
 
 struct ResolverArgs {
   const Value v;
-  const Exp_Call *e;
+  Exp_Call *const e;
   const m_str tmpl_name;
   const Type_List types;
 };
@@ -32,13 +32,13 @@ ANN static inline m_bool tmpl_valid(const Env env, const Func_Def fdef) {
       check_traverse_fdef(env, fdef) > 0;
 }
 
-ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, const Exp_Call *exp) {
+ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, Exp_Call *const exp) {
   if(!tmpl_valid(env, fdef))
     return NULL;
   const Func f = fdef->base->func;
   const Func next = f->next;
   f->next = NULL;
-  const Func func = find_func_match(env, f, exp->args);
+  const Func func = find_func_match(env, f, exp);
   f->next = next;
   if(func)
     set_fflag(func, fflag_tmpl | fflag_valid);
@@ -47,7 +47,7 @@ ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, const Exp_Call *
 
 ANN static inline Func ensure_fptr(const Env env, struct ResolverArgs* ra, const Fptr_Def fptr) {
   CHECK_BO(traverse_fptr_def(env, fptr))
-  return find_func_match(env, fptr->base->func, ra->e->args);
+  return find_func_match(env, fptr->base->func, ra->e);
 }
 
 ANN static Func fptr_match(const Env env, struct ResolverArgs* ra) {
@@ -76,7 +76,7 @@ ANN static Func fptr_match(const Env env, struct ResolverArgs* ra) {
 
 ANN static Func tmpl_exists(const Env env, struct ResolverArgs* ra, const Value exists) {
   if(env->func == exists->d.func_ref)
-    return find_func_match(env, env->func, ra->e->args) ? env->func : NULL;
+    return find_func_match(env, env->func, ra->e) ? env->func : NULL;
   return ensure_tmpl(env, exists->d.func_ref->def, ra->e);
 }
 
@@ -106,7 +106,7 @@ ANN static Func func_match(const Env env, struct ResolverArgs* ra) {
   return NULL;
 }
 
-ANN static Func find_tmpl(const Env env, const Value v, const Exp_Call* exp, const m_str tmpl_name) {
+ANN static Func find_tmpl(const Env env, const Value v, Exp_Call *const exp, const m_str tmpl_name) {
   const Type_List types = exp->tmpl->call;
   const Func former = env->func;
   const m_uint scope = env->scope->depth;
@@ -124,7 +124,7 @@ ANN static Func find_tmpl(const Env env, const Value v, const Exp_Call* exp, con
   return m_func;
 }
 
-ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) {
+ANN static Func _find_template_match(const Env env, const Value v, Exp_Call *const exp) {
   DECL_OO(const m_str, tmpl_name, = tl2str(env->gwion, exp->tmpl->call, exp->func->pos))
   const Func f = find_tmpl(env, v, exp, tmpl_name);
   free_mstr(env->gwion->mp, tmpl_name);
@@ -138,7 +138,7 @@ ANN static inline m_bool check_call(const Env env, const Exp_Call* exp) {
   return GW_OK;
 }
 
-ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) {
+ANN Func find_template_match(const Env env, const Value value, Exp_Call *const exp) {
   CHECK_BO(check_call(env, exp))
   const Func f = _find_template_match(env, value, exp);
   if(f)
diff --git a/tests/ufcc/has_func.gw b/tests/ufcc/has_func.gw
new file mode 100644 (file)
index 0000000..3bd7ec2
--- /dev/null
@@ -0,0 +1,13 @@
+class C {
+  fun void test(int i) {
+   <<< "member func called test">>>;
+  }
+}
+
+fun void test(C c) {
+ <<< "func called test">>>;
+}
+
+const C c;
+c.test();
+c.test(2);
diff --git a/tests/ufcc/no_func.gw b/tests/ufcc/no_func.gw
new file mode 100644 (file)
index 0000000..60080d8
--- /dev/null
@@ -0,0 +1,9 @@
+#! [contains] func called test
+class C {}
+
+fun void test(C c) {
+ <<< "func called test">>>;
+}
+
+const C c;
+c.test();