]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve lambdas
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 20 Jun 2020 09:30:35 +0000 (11:30 +0200)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 20 Jun 2020 09:30:35 +0000 (11:30 +0200)
src/lib/func.c
src/parse/check.c

index b579a9db729896699f9f34359dcd8a945850745a..3d26ee1f6f48f6ed33078cfba7b5195f3e022ae4 100644 (file)
@@ -152,7 +152,11 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l, const Func_Def def
     ERR_B(exp_self(l)->pos, _("argument number does not match for lambda"))
   l->def->flag = def->flag;
   l->def->base->td = cpy_type_decl(env->gwion->mp, def->base->td);
-  CHECK_BB(traverse_func_def(env, l->def))
+  SET_FLAG(l->def, abstract); // mark as non immediate lambda
+  map_set(&env->curr->info->value->map, (m_uint)l->def->base, env->scope->depth);
+  const m_bool ret = traverse_func_def(env, l->def);
+  map_remove(&env->curr->info->value->map, (m_uint)l->def->base);
+  CHECK_BB(ret)
   arg = l->def->base->args;
   while(arg) {
     arg->td = NULL;
index 677b63c8c5ff2f820abe6997b63d9f25b22859f7..7eb363c49a45f1e46b7509a81a615b42c9a57394 100644 (file)
@@ -286,19 +286,37 @@ static inline Nspc value_owner(const Value v) {
   return v ? v->from->owner : NULL;
 }
 
+ANN static inline m_bool lambda_valid(const Env env, const Exp_Primary* exp) {
+  const Value val = exp->value;
+  const Symbol sym = insert_symbol(val->name);
+  const vtype xid = (vtype)sym;
+  const Vector vec = (Vector)&env->curr->info->value->ptr;
+  const m_uint scope = map_get(&env->curr->info->value->map, (m_uint)env->func->def->base) + 1;
+  if((val != (Value)map_get((Map)vector_back(vec), xid) && !nspc_lookup_value1(env->global_nspc, sym) &&
+    val != (Value)map_get((Map)vector_at(vec, vector_size(vec) - scope), xid)) &&
+    val->from->owner_class != env->class_def)
+      ERR_B(exp_self(exp)->pos, _("variable '%s' is not in lambda scope"), val->name)
+  return GW_OK;
+}
+
 ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
-  const Symbol var = *data;
+  const Symbol sym = *data;
   const Value v = check_non_res_value(env, data);
   if(!v || !GET_FLAG(v, valid) || (v->from->ctx && v->from->ctx->error)) {
     env_err(env, prim_pos(data),
-          _("variable %s not legit at this point."), s_name(var));
-    did_you_mean_nspc(value_owner(v) ?: env->curr, s_name(var));
+          _("variable %s not legit at this point."), s_name(sym));
+    if(v)
+      did_you_mean_nspc(value_owner(v) ?: env->curr, s_name(sym));
     return NULL;
   }
+  prim_self(data)->value = v;
+  if(env->func) {
+    if(GET_FLAG(env->func->def, abstract))
+      CHECK_BO(lambda_valid(env, prim_self(data)))
   if(env->func && !GET_FLAG(v, const) && v->from->owner)
     UNSET_FLAG(env->func, pure);
+  }
   SET_FLAG(v, used);
-  prim_self(data)->value = v;
   if(GET_FLAG(v, const))
     exp_setmeta(prim_exp(data), 1);
   if(v->from->owner_class) {