]> Nishi Git Mirror - gwion.git/commitdiff
Dev (#246)
authorJérémie Astor <fennecdjay@gmail.com>
Wed, 20 Apr 2022 11:57:53 +0000 (13:57 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Apr 2022 11:57:53 +0000 (13:57 +0200)
* :art: Locales :smile:

* :bug: Update fmt

* :art: Fully implement partial application

* :art: LGTM

* :art: Improve partial non used checking

* :wrench: install submodules if not present

* :art: Update README

* :art: test partial application

34 files changed:
Makefile
README.md
ast
fmt
highlighters/gwion.kak
highlighters/gwion.nanorc
include/emit.h
include/env/context.h
include/env/type.h
include/lang_private.h
include/partial.h [new file with mode: 0644]
plug
src/compile.c
src/emit/emit.c
src/gwion.c
src/lib/curry.c [deleted file]
src/lib/dict.c
src/lib/engine.c
src/lib/lib_func.c
src/main.c
src/parse/check.c
src/parse/partial.c [new file with mode: 0644]
src/parse/scan2.c
src/parse/template.c
tests/locale/locale.basic.gw [new file with mode: 0644]
tests/locale/locale_default_args.gw [new file with mode: 0644]
tests/locale/locale_with_args.gw [new file with mode: 0644]
tests/partial/apms1.gw [moved from tests/apms/apms1.gw with 100% similarity]
tests/partial/apms2.gw [moved from tests/apms/apms2.gw with 100% similarity]
tests/partial/apms3.gw [moved from tests/apms/apms3.gw with 100% similarity]
tests/partial/partial_ambiguous.gw [new file with mode: 0644]
tests/partial/partial_no_match.gw [new file with mode: 0644]
tests/partial/partial_not_used.gw [new file with mode: 0644]
util

index 12d81b4f9b70fead47a0e5147598a6bd7fd4431a..b2f29edc37a8684cf3f1c474c1bce8aa39ff2bdd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -65,7 +65,10 @@ CFLAGS += -Wno-pedantic
 
 CFLAGS += -DGWION_BUILTIN
 
-all: options-show ${PRG}
+all: deps options-show ${PRG}
+
+deps:
+       [ "$(shell ls util | wc -l)" = "0" ] && git submodule update --init --recursive || true
 
 ${PRG}: ${GWLIBS} src/main.o
        @$(info link ${PRG})
index 697f377197383a85959a2baa3e55546da4fa55c0..a62c41b8d4cf9dc8389599c468d0b5052ab0c938 100644 (file)
--- a/README.md
+++ b/README.md
@@ -4,9 +4,6 @@
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2417/badge)](https://bestpractices.coreinfrastructure.org/projects/2417)
 [![Coverage](https://raw.githubusercontent.com/Gwion/gwion-coverage-report/master/badge.svg?sanitize=true)](https://fennecdjay.github.io/gwion-coverage-report/master)
 [![Line Count](https://tokei.rs/b1/github/Gwion/Gwion)](https://github.com/fennecdjay/Gwion)
-<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
-[![All Contributors](https://img.shields.io/badge/all_contributors-16-orange.svg)](#contributors)
-<!-- ALL-CONTRIBUTORS-BADGE:END --> 
 ![Linux](https://github.com/Gwion/Gwion/workflows/Linux/badge.svg)
 ![MacOs](https://github.com/Gwion/Gwion/workflows/MacOs/badge.svg)
 ![Windows](https://github.com/Gwion/Gwion/workflows/Windows/badge.svg)
@@ -162,41 +159,4 @@ If there's anything you see that can make Gwion better, please let us know!
 ## Acknowledgements.
 The whole [Chuck](http://chuck.cs.princeton.edu/) team, for inspiration.  
 [Paul Batchelor](https://github.com/PaulBatchelor) and the awesome [soundpipe](https://github.com/PaulBatchelor/Soundpipe) library, that got me started.
-
-## Contributors
-
-Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
-<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
-<!-- prettier-ignore-start -->
-<!-- markdownlint-disable -->
-<table>
-  <tr>
-    <td align="center"><a href="http://paulbatchelor.github.io"><img src="https://avatars3.githubusercontent.com/u/8139389?v=4" width="100px;" alt=""/><br /><sub><b>Paul Batchelor</b></sub></a><br /><a href="#question-PaulBatchelor" title="Answering Questions">💬</a> <a href="https://github.com/Gwion/Gwion/issues?q=author%3APaulBatchelor" title="Bug reports">🐛</a> <a href="https://github.com/fennecdjay/Gwion/commits?author=PaulBatchelor" title="Code">💻</a> <a href="#ideas-PaulBatchelor" title="Ideas, Planning, & Feedback">🤔</a></td>
-    <td align="center"><a href="https://github.com/originalsouth"><img src="https://avatars1.githubusercontent.com/u/5300799?v=4" width="100px;" alt=""/><br /><sub><b>Benny</b></sub></a><br /><a href="#question-originalsouth" title="Answering Questions">💬</a> <a href="https://github.com/Gwion/Gwion/issues?q=author%3Aoriginalsouth" title="Bug reports">🐛</a> <a href="https://github.com/fennecdjay/Gwion/commits?author=originalsouth" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/scalarwaves"><img src="https://avatars1.githubusercontent.com/u/4212896?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Prentice</b></sub></a><br /><a href="#question-scalarwaves" title="Answering Questions">💬</a> <a href="https://github.com/Gwion/Gwion/issues?q=author%3Ascalarwaves" title="Bug reports">🐛</a> <a href="https://github.com/fennecdjay/Gwion/commits?author=scalarwaves" title="Code">💻</a> <a href="#ideas-scalarwaves" title="Ideas, Planning, & Feedback">🤔</a></td>
-    <td align="center"><a href="https://github.com/Aleserche"><img src="https://avatars3.githubusercontent.com/u/2920837?v=4" width="100px;" alt=""/><br /><sub><b>aleserche</b></sub></a><br /><a href="https://github.com/Gwion/Gwion/commits?author=Aleserche" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/Pranav2612000"><img src="https://avatars3.githubusercontent.com/u/20909078?v=4" width="100px;" alt=""/><br /><sub><b>Pranav Joglekar</b></sub></a><br /><a href="#userTesting-Pranav2612000" title="User Testing">📓</a> <a href="https://github.com/Gwion/Gwion/commits?author=Pranav2612000" title="Documentation">📖</a></td>
-    <td align="center"><a href="http://dev.to/amberisvibin"><img src="https://avatars3.githubusercontent.com/u/63863236?v=4" width="100px;" alt=""/><br /><sub><b>Amber</b></sub></a><br /><a href="#question-amberisvibin" title="Answering Questions">💬</a> <a href="https://github.com/Gwion/Gwion/commits?author=amberisvibin" title="Documentation">📖</a> <a href="#ideas-amberisvibin" title="Ideas, Planning, & Feedback">🤔</a></td>
-    <td align="center"><a href="https://github.com/TotallyNotChase"><img src="https://avatars0.githubusercontent.com/u/44284917?v=4" width="100px;" alt=""/><br /><sub><b>Chase</b></sub></a><br /><a href="https://github.com/Gwion/Gwion/commits?author=TotallyNotChase" title="Code">💻</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/nithin-pankaj"><img src="https://avatars2.githubusercontent.com/u/15152472?v=4" width="100px;" alt=""/><br /><sub><b>Nithin Pankaj</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=nithin-pankaj" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/evayde"><img src="https://avatars1.githubusercontent.com/u/25255815?v=4" width="100px;" alt=""/><br /><sub><b>Enrico Gruner</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=evayde" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/umer2001"><img src="https://avatars2.githubusercontent.com/u/35496058?v=4" width="100px;" alt=""/><br /><sub><b>Muhammad Umer Farooq</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=umer2001" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/a-mere-peasant"><img src="https://avatars3.githubusercontent.com/u/50142453?s=400&u=4844f21d4f48431d854307ecdf4d1f4d80977ab9&v=4" width="100px;" alt=""/><br /><sub><b>Harsh Jain</b></sub></a><br /><a href="https://github.com/Gwion/Gwion/commits?author=a-mere-peasant" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://github.com/ry-v1"><img src="https://avatars1.githubusercontent.com/u/72290009?v=4" width="100px;" alt=""/><br /><sub><b>ry-v1</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=ry-v1" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://github.com/deekts"><img src="https://avatars0.githubusercontent.com/u/51462833?v=4" width="100px;" alt=""/><br /><sub><b>deekts</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=deekts" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/forrcaho"><img src="https://avatars3.githubusercontent.com/u/492742?v=4" width="100px;" alt=""/><br /><sub><b>Forrest Cahoon</b></sub></a><br /><a href="#ideas-forrcaho" title="Ideas, Planning, & Feedback">🤔</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/SenorGrande"><img src="https://avatars2.githubusercontent.com/u/22025776?v=4" width="100px;" alt=""/><br /><sub><b>Connor Hewett</b></sub></a><br /><a href="https://github.com/fennecdjay/Gwion/commits?author=SenorGrande" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/euppal"><img src="https://avatars2.githubusercontent.com/u/67026187?v=4" width="100px;" alt=""/><br /><sub><b>Ethan Uppal</b></sub></a><br /><a href="#ideas-PaulBatchelor" title="Ideas, Planning, & Feedback">🤔</a></td>
-  </tr>
-</table>
-
-<!-- markdownlint-enable -->
-<!-- prettier-ignore-end -->
-<!-- ALL-CONTRIBUTORS-LIST:END -->
-This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
-
->    NOTE: if you should be on the list of contributors but we forgot you, don't be shy and let us know!
+not to forget these wonderful people ([emoji key](https://gwion.github.io/Gwion/Contributing/Contributors.html)):
diff --git a/ast b/ast
index c13d5da0476a1409d2f501e7e014a58f55be9fd8..27fba9f6ef3faf79695c95d57afdb4267bc751b5 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit c13d5da0476a1409d2f501e7e014a58f55be9fd8
+Subproject commit 27fba9f6ef3faf79695c95d57afdb4267bc751b5
diff --git a/fmt b/fmt
index 3bb27f71298a13e4d31b3dda1b67c854086298be..cf3523938d57ae658952b1104f8b91dbd3dd8ea2 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit 3bb27f71298a13e4d31b3dda1b67c854086298be
+Subproject commit cf3523938d57ae658952b1104f8b91dbd3dd8ea2
index c342e51f22cb42c6370156a808e23bf432a32ffd..e79652f94d0aa7e3ddbba90972f9bb4ab34f0c71 100644 (file)
@@ -22,10 +22,10 @@ provide-module -override gwion %{
                        where when case varloop
                        defer try perform handle retry
                        fun function typedef distinct funptr
-                       new spork fork'
+                       new spork fork locale'
 
                attributes='const var static private public protect variadic template samp ms second minute delay'
-               types='auto int float bool dur void Object Shred Event'
+               types='auto int float bool dur time void Object Shred Event'
                values='true false none this now me adc dac maybe'
                builtins='__file__ __line__ __func__'
                entities='class struct trait union enum'
index b6ed677b1956763ad756e21f1ecb38b5f7b09b40..52729fa17008f02bc813f44ee287a515da5b6795 100644 (file)
@@ -37,14 +37,14 @@ color mauve "\<UsrUGen\>"
 color mauve "\<Ref\>"
 comment "#!"
 
-color italic,red start="#\<(pragma|include|define|ifdef|ifndef|undef|endif|import)\>" end="$"
-
 color brightred "\<(typeof|spork|fork)\>"
 color lightred "\<(second|ms|day|samp|minute|hour)\>"
 color brightcyan "\<(maybe)\>"
 color cyan "\<(adc|blackhole)\>"
 
-color brightgreen "\<(try|handle|perform|retry|class|struct|trait|union|enum|fun|operator|funptr|typedef|distinct|new)\>"
+color brightgreen "\<(try|handle|perform|retry|class|struct|trait|union|enum|fun|locale|operator|funptr|typedef|distinct|new)\>"
+color italic,red start="#\<(pragma|include|define|ifdef|ifndef|undef|endif|import|locale)\>" end="$"
+color italic,red "#locale"
 color italic,yellow "extends"
 color italic,brightgreen "\<(final|abstract)\>"
 color lightgreen "@[a-zA-Z]+[a-zA-Z0-9_]*|&[a-zA-Z]+[a-zA-Z0-9_]*"
index 808879e1ffb7508cf262f056684f3871d1d9bd08..a5928716511035aea4a8d22d0e7e19c71d01a8c0 100644 (file)
@@ -52,6 +52,7 @@ struct Emitter_ {
   struct Gwion_ *      gwion;
   struct EmitterInfo_ *info;
   struct Vector_       stack;
+  Func                 locale;
   uint16_t             this_offset;   // reset
   uint16_t             vararg_offset; // reset
 };
index 77b4bb2e12135e9fe9df30fd0acf49c80ed84e48..af191283bdc685a894064476b57038354c3cc1d6 100644 (file)
@@ -5,7 +5,6 @@ struct Context_ {
   Nspc     nspc;
   m_str    name;
   Ast      tree;
-  Func locale;
   uint16_t ref;
   uint16_t weight;
   bool     error;
index 23938edf0f9add5ee89b95d54c7a32a13aad083b..6a3e1a3a781ac909539c36e9b2ba74e9e3467f5d 100644 (file)
@@ -140,7 +140,6 @@ typedef enum {
   et_union,
   et_auto,
   et_none,
-  et_apms,
   et_dict,
   MAX_TYPE
 } type_enum;
index 825edae19791cc42ce100edc26a0ba8fc63bd706..c60954a6261c7f1b5a634423c06de784fb62057b 100644 (file)
@@ -19,5 +19,4 @@ ANN m_bool import_ref(const Gwi gwi);
 ANN m_bool import_deep_equal(const Gwi gwi);
 ANN m_bool import_dict(const Gwi gwi);
 ANN m_bool import_gack(const Gwi gwi);
-ANN m_bool import_curry(const Gwi gwi);
 #endif
diff --git a/include/partial.h b/include/partial.h
new file mode 100644 (file)
index 0000000..0a6603e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __PARTIAL_APPLICATION
+#define __PARTIAL_APPLICATION
+
+ANN Type partial_type(const Env, Exp_Call *const);
+ANN void print_signature(const Func f);
+
+ANN static inline bool func_match_inner(const Env env, const Exp e,
+                                        const Type t, const bool implicit,
+                                        const bool specific) {
+  if (specific ? e->type == t : isa(e->type, t) > 0) // match
+    return true;
+  return !implicit ? false : check_implicit(env, e, t) > 0;
+}
+
+ANN static inline bool is_typed_hole(const Env env, const Exp exp) {
+  return exp->exp_type == ae_exp_cast && is_hole(env, exp->d.exp_cast.exp);
+}
+#endif
diff --git a/plug b/plug
index 49a4be94f9c4042f854dc82c8c6e598ec9d4df29..524694345a2e9ed7b257bf6ff8a3d70940e5aa61 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit 49a4be94f9c4042f854dc82c8c6e598ec9d4df29
+Subproject commit 524694345a2e9ed7b257bf6ff8a3d70940e5aa61
index 5a0e380deba8c12c75eed7424345af05abf0d477..2974fdef081ac0de3d1a59a259bb3c7c20eb5593 100644 (file)
@@ -103,7 +103,6 @@ ANN static inline m_bool _passes(struct Gwion_ *gwion, struct Compiler *c) {
 ANN static inline m_bool passes(struct Gwion_ *gwion, struct Compiler *c) {
   const Env     env = gwion->env;
   const Context ctx = new_context(env->gwion->mp, c->ast, env->name);
-//ctx->locale = nspc_lookup_value1(gwion->env->global_nspc, insert_symbol(gwion->st, "@DefaultLocale"))->d.func_ref;
   env_reset(env);
   load_context(ctx, env);
   const m_bool ret = _passes(gwion, c);
index 0b6acd14b9d105a151abc96cde9f69c786c01137..5d5ce8589900d76ece415c75caf86a8d5943bf46 100644 (file)
@@ -18,6 +18,7 @@
 #include "specialid.h"
 #include "vararg.h"
 #include "looper.h"
+#include "shreduler_private.h"
 
 #undef insert_symbol
 #define insert_symbol(a) insert_symbol(emit->gwion->st, (a))
@@ -912,7 +913,7 @@ ANN static m_bool emit_prim_interp(const Emitter emit, const Exp *exp) {
   emit_localx(emit, emit->gwion->type[et_string]);
   return GW_OK;
 }
-#include "shreduler_private.h"
+
 ANN static m_bool emit_ensure_func(const Emitter emit, const Func f) {
   const struct ValueFrom_ *from = f->value_ref->from;
   if(from->owner_class)
@@ -925,32 +926,26 @@ ANN static m_bool emit_ensure_func(const Emitter emit, const Func f) {
 }
 
 ANN static m_bool emit_prim_locale(const Emitter emit, const Symbol *id) {
-  CHECK_BB(emit_ensure_func(emit, emit->env->context->locale));
+  if(emit->locale->def->d.code) {
+    const Stmt stmt = mp_vector_at((emit->locale->def->d.code->d.stmt_code.stmt_list), struct Stmt_, 0);
+    const Func f = stmt->d.stmt_exp.val->d.exp_call.func->type->info->func;
+    CHECK_OB(emit_ensure_func(emit, f));
+  }
+  CHECK_OB(emit_ensure_func(emit, emit->locale));
   emit_push_code(emit, "locale"); // new code {
-
-  //   push args
   const M_Object string = new_string(emit->gwion, s_name(*id));
   regpushi(emit, (m_uint)string);
-
-  regpushi(emit, (m_uint)emit->env->context->locale->code);
-  emit_exp_call1(emit, emit->env->context->locale, true);
-
-  regpop(emit, emit->env->context->locale->def->base->ret_type->size);
+  regpushi(emit, (m_uint)emit->locale->code);
+  emit_exp_call1(emit, emit->locale, true);
+  regpop(emit, emit->locale->def->base->ret_type->size);
   const VM_Code code = finalyze(emit, EOC);
   const VM_Shred shred = new_vm_shred(emit->gwion->mp, code);
   vm_add_shred(emit->gwion->vm, shred);
   shred->info->me->ref++;
   vm_run(emit->gwion->vm);
   emit->gwion->vm->bbq->is_running = true;
-  if(tflag(emit->env->context->locale->def->base->ret_type, tflag_float)) {
-    const Instr instr = emit_add_instr(emit, RegPushImm2);
-    instr->f = *(m_float*)shred->reg;
-  } else if(emit->env->context->locale->def->base->ret_type->size == SZ_INT)
-    regpushi(emit, *(m_uint*)shred->reg);
-  else {
-    // here we would need to deallocate
-    ERR_B(prim_pos(id), "not implemented atm");
-  }
+  const Instr instr = emit_add_instr(emit, RegPushImm2);
+  instr->f = *(m_float*)shred->reg;
   return GW_OK;
 }
 
@@ -1990,12 +1985,12 @@ ANN2(1,2) static Instr _flow(const Emitter emit, const Exp e, Instr *const instr
 //  CHECK_BO(emit_exp_pop_next(emit, e));
   CHECK_BO(emit_exp(emit, e));
   {
-    const Instr instr = (Instr)vector_back(&emit->code->instr);
-    if(instr->execute == fast_except) {
+    const Instr ex = (Instr)vector_back(&emit->code->instr);
+    if(ex->execute == fast_except) {
       vector_rem(&emit->code->instr, vector_size(&emit->code->instr) - 1);
-      if(instr->m_val2)
-        mp_free2(emit->gwion->mp, sizeof(struct FastExceptInfo), (struct FastExceptInfo*)instr->m_val2);
-      free_instr(emit->gwion, instr);
+      if(ex->m_val2)
+        mp_free2(emit->gwion->mp, sizeof(struct FastExceptInfo), (struct FastExceptInfo*)ex->m_val2);
+      free_instr(emit->gwion, ex);
     }
   }
   if(instr)
@@ -2837,11 +2832,14 @@ ANN static m_bool emit_stmt_match(const Emitter             emit,
 
 ANN static m_bool emit_stmt_pp(const Emitter          emit,
                                const struct Stmt_PP_ *stmt) {
-  if (stmt->pp_type == ae_pp_pragma) {
+  if (stmt->pp_type == ae_pp_include)
+    emit->env->name = stmt->data;
+  else if (stmt->pp_type == ae_pp_locale)
+    emit->locale = stmt->exp->d.exp_lambda.def->base->func;
+  else if (stmt->pp_type == ae_pp_pragma) {
     if (!strncmp(stmt->data, "unroll", strlen("unroll")))
       emit->info->unroll = strtol(stmt->data + 6, NULL, 10);
-  } else if (stmt->pp_type == ae_pp_include)
-    emit->env->name = stmt->data;
+  }
   return GW_OK;
 }
 
@@ -3078,7 +3076,9 @@ ANN m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
 ANN m_bool emit_func_def(const Emitter emit, const Func_Def fdef) {
   const uint16_t depth = emit->env->scope->depth;
   emit->env->scope->depth = 0;
+  const Func locale = emit->locale;
   const m_bool ret = _emit_func_def(emit, fdef);
+  emit->locale = locale;
   emit->env->scope->depth = depth;
   return ret;
 }
@@ -3131,10 +3131,8 @@ ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) {
   return ret;
 }
 
-ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
-  if (tmpl_base(cdef->base.tmpl)) return GW_OK;
+ANN static m_bool _emit_class_def(const Emitter emit, const Class_Def cdef) {
   const Type      t = cdef->base.type;
-  if (tflag(t, tflag_emit)) return GW_OK;
   set_tflag(t, tflag_emit);
   const Class_Def c = t->info->cdef;
   if (c->base.ext && t->info->parent->info->cdef &&
@@ -3153,6 +3151,15 @@ ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
   return GW_OK;
 }
 
+ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
+  if (tmpl_base(cdef->base.tmpl)) return GW_OK;
+  if (tflag(cdef->base.type, tflag_emit)) return GW_OK;
+  const Func locale = emit->locale;
+  const m_bool ret = _emit_class_def(emit, cdef);
+  emit->locale = locale;
+  return ret;
+}
+
 ANN static inline void emit_free_code(const Emitter emit, Code *code) {
   if (vector_size(&code->instr)) free_code_instr(&code->instr, emit->gwion);
   free_code(emit->gwion->mp, code);
@@ -3177,6 +3184,7 @@ ANN static inline void emit_clear(const Emitter emit) {
 
 ANN m_bool emit_ast(const Env env, Ast *ast) {
   const Emitter emit  = env->gwion->emit;
+  const Func locale = emit->locale;
   emit_clear(emit);
   emit->code          = new_code(emit, emit->env->name);
   emit_push_scope(emit);
@@ -3187,5 +3195,6 @@ ANN m_bool emit_ast(const Env env, Ast *ast) {
   else
     emit_free_stack(emit);
   emit_clear(emit);
+  emit->locale = locale;
   return ret;
 }
index 9fca9311e246c01a88af5c57d3845c14d23f0d0a..0f7f94e81f31bbf47eaa70f0da601f682d2d6c25 100644 (file)
@@ -68,6 +68,14 @@ ANN static void gwion_core(const Gwion gwion) {
   gwion->vm->gwion = gwion->emit->gwion = gwion->env->gwion = gwion;
 }
 
+
+ANN static Func gwion_locale(const Gwion gwion) {
+   const Nspc nspc = gwion->env->curr;
+   const Symbol sym = insert_symbol(gwion->st, "BasicLocale");
+   const Value v = nspc_lookup_value1(nspc, sym);
+   return v->d.func_ref;
+}
+
 ANN static m_bool gwion_ok(const Gwion gwion, CliArg *arg) {
   CHECK_BB(plug_ini(gwion, &arg->lib));
   shreduler_set_loop(gwion->vm->shreduler, arg->loop);
@@ -75,6 +83,7 @@ ANN static m_bool gwion_ok(const Gwion gwion, CliArg *arg) {
     plug_run(gwion, &arg->mod);
     if (type_engine_init(gwion)) {
       gwion->vm->cleaner_shred = gwion_cleaner(gwion);
+      gwion->emit->locale = gwion_locale(gwion);
       (void)arg_compile(gwion, arg);
       return GW_OK;
     }
diff --git a/src/lib/curry.c b/src/lib/curry.c
deleted file mode 100644 (file)
index 75e84fd..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "instr.h"
-#include "emit.h"
-#include "gwion.h"
-#include "object.h"
-#include "operator.h"
-#include "import.h"
-#include "gwi.h"
-#include "traverse.h"
-#include "parse.h"
-
-ANN static Arg_List curry_arg_list(const Env env, const Arg_List base, const Exp e) {
-  Arg_List args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0);
-  Exp next = e;
-  uint32_t i = 0;
-  while(next) {
-    if(is_hole(env, next)) {
-      char c[256];
-      sprintf(c, "@%u\n", args->len);
-      Type_Decl *td = cpy_type_decl(env->gwion->mp, mp_vector_at(base, Arg, i)->td);
-      Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c) }};
-      mp_vector_add(env->gwion->mp, &args, Arg, arg);
-    }
-    i++;
-    next = next->next;
-  }
-  return args;
-}
-
-ANN2(1) static Func_Base *curry_base(const Env env, const Func_Base *base, Exp earg, const loc_t loc) {
-  Arg_List args = earg ? curry_arg_list(env, base->args, earg) : NULL;
-  Func_Base *fb = new_func_base(env->gwion->mp, cpy_type_decl(env->gwion->mp, base->td), lambda_name(env->gwion->st, loc.first), args, ae_flag_none, loc);
-  fb->fbflag |= fbflag_lambda;
-  return fb;
-}
-
-ANN static Exp curry_call(const Env env, Exp e) {
-  Exp base = NULL, arg;
-  uint32_t i = 0;
-  while(e) {
-    if(is_hole(env, e)) {
-      char c[256];
-      sprintf(c, "@%u\n", i++);
-      const Exp next = new_prim_id(env->gwion->mp, insert_symbol(c), e->pos);
-      if(base) arg = arg->next = next;
-      else arg = base = next;
-    } else {
-      const Exp next = cpy_exp(env->gwion->mp, e);
-      if(base) arg = arg->next = next;
-      else arg = base = next;
-    }
-    e = e->next;
-  }
-  return base;
-}
-
-ANN static Stmt curry_code(const Env env, const Exp efun, const Exp earg) {
-  Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
-  const Exp arg = curry_call(env, earg);
-  const Exp exp = new_exp_call(env->gwion->mp, efun, arg, efun->pos);
-  Stmt stmt = mp_vector_at(slist, struct Stmt_, 0);
-  stmt->stmt_type = ae_stmt_return;
-  stmt->d.stmt_exp.val = exp;
-  return new_stmt_code(env->gwion->mp, slist, efun->pos);
-}
-
-ANN static Type curry_type(const Env env, const Exp exp, const Exp efun, const Exp earg) {
-  Func_Base *base = curry_base(env, efun->type->info->func->def->base, earg, exp->pos);
-  Stmt code = curry_code(env, efun, earg);
-  exp->d.exp_lambda.def = new_func_def(env->gwion->mp, base, code);
-  exp->exp_type = ae_exp_lambda;
-  return check_exp(env, exp);
-}
-
-static OP_CHECK(opck_curry) {
-  Exp_Call *call = (Exp_Call*)data;
-  if(!call->args)
-    ERR_N(exp_self(call)->pos, _("`curry` requires a function as first argument"));
-  const Exp efun = call->args;
-  const Exp earg = efun->next;
-  efun->next = NULL;
-  const Type ret = check_exp(env, efun)
-    ? curry_type(env, exp_self(call), efun, earg)
-    : env->gwion->type[et_error];
-  mp_free(env->gwion->mp, Exp, earg);
-  return ret;
-}
-
-GWION_IMPORT(curry) {
-  GWI_BB(gwi_func_ini(gwi, "@function", "curry"));
-  GWI_BB(gwi_func_end(gwi, (f_xfun)1, ae_flag_none));
-
-  const Env env = gwi->gwion->env; // no need
-  const Func f = (Func)map_at(&env->curr->info->func->map, map_size(&env->curr->info->func->map) - 1);
-  const struct Op_Func   opfunc = {.ck = opck_curry};
-  const struct Op_Import opi    = {
-      .rhs  = f->value_ref->type,
-      .func = &opfunc,
-      .data = (uintptr_t)f,
-      .op   = insert_symbol("@func_check")};
-  CHECK_BB(add_op(gwi->gwion, &opi));
-  return GW_OK;
-}
-
index 0e85c398e9dbbaa8c562890f45dced617f06a926..98d4f121a0fabde8ae80554ba4dd216f89190aa9 100644 (file)
@@ -488,8 +488,8 @@ static OP_EMIT(opem_dict_remove) {
   CHECK_BB(emit_dict_iter(emit, hinfo, &opi, &call, bin->lhs));
   if(hinfo->keyk || hinfo->valk) {
     clear_fn *const fn = clear[hinfo->keyk][hinfo->valk];
-    const Instr clear = emit_add_instr(emit, hmap_remove_clear);
-    clear->m_val = (m_uint)fn;
+    const Instr instr = emit_add_instr(emit, hmap_remove_clear);
+    instr->m_val = (m_uint)fn;
   }
 
   const Instr pushval = emit_add_instr(emit, hmap_remove);
index c4a607fa8c886bc12bfa3762985860869d476e3f..adab057eef933c4cf4002042c1a7579bc286e789 100644 (file)
@@ -56,6 +56,28 @@ static FREEARG(freearg_release) {
   vector_release(&v);
 }
 
+ANN static m_float basic_locale(m_str str) {
+  const char base = str[0];
+  str++;
+  if(base < 'A' || base > 'G') return -1;
+  m_int bnote = base - 'A';
+  if(*str == '#') { bnote++; str++; }
+  else if(*str == 'b') { bnote--; str++; }
+  char *remainder;
+  const long octave = strtol(str, &remainder, 10);
+  if(*remainder != '\0') return -1;
+  const int note = bnote + 12 * octave + 21;
+  return (pow(2, (note - 69) / 12.0) * 440.0);
+}
+
+static SFUN(BasicLocale) {
+  const M_Object arg = *(M_Object*)MEM(0);
+  const m_float ret = basic_locale(STRING(arg));
+  if(ret == -1.0)
+    handle(shred, "invalid value for locale");
+  *(m_float*)RETURN = ret;
+}
+
 ANN static m_bool import_core_libs(const Gwi gwi) {
   gwidoc(gwi, "one type to rule them all.");
   const Type t_class = gwi_mk_type(gwi, "Class", SZ_INT, NULL);
@@ -141,10 +163,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   /*set_tflag(t_lambda, tflag_infer);*/
   GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
 
-  gwidoc(gwi, "Mark function as apms.");
-  const Type t_apms = gwi_mk_type(gwi, "@apms", 0, NULL);
-  GWI_BB(gwi_set_global_type(gwi, t_apms, et_apms))
-
   gwidoc(gwi, "type for internal pointer data.");
   GWI_BB(gwi_typedef_ini(gwi, "int", "@internal"))
   GWI_BB(gwi_typedef_end(gwi, ae_flag_none))
@@ -187,7 +205,9 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(import_gack(gwi));
 
 
-  GWI_BB(import_curry(gwi));
+gwi_func_ini(gwi, "float", "BasicLocale");
+gwi_func_arg(gwi, "string", "str");
+gwi_func_end(gwi, BasicLocale, ae_flag_none);
 
   // seemed need at a point to ease liking
   gwi_enum_ini(gwi, "@hidden_enum");
index d4c29a925e7b2948e7aadf7a6014a6ea9f2a99d2..0433c872dc550c22e955e775f41b6fb3684c4fd0 100644 (file)
@@ -18,7 +18,6 @@ static OP_CHECK(opck_func_call) {
   Exp_Call    call = {.func = bin->rhs, .args = bin->lhs};
   Exp         e    = exp_self(bin);
   e->exp_type      = ae_exp_call;
-  call.apms = true;
   memcpy(&e->d.exp_call, &call, sizeof(Exp_Call));
   return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_error];
 }
@@ -36,54 +35,6 @@ ANN static inline Exp cpy_nonext(const Env env, const Exp e) {
   return ret;
 }
 
-ANN static Exp order_apms(const Env env, Exp fn, const Exp _arg) {
-  const MemPool mp   = env->gwion->mp;
-  Exp           base = NULL;
-  Exp           next = NULL;
-  Exp           arg  = _arg;
-  do {
-    const bool hole = is_hole(env, fn);
-    const Exp  curr = !hole ? fn : arg;
-    if (hole) {
-      if (!arg) {
-        if (base) free_exp(mp, base);
-        ERR_O(fn->pos, "not enough arguments for holes");
-      }
-      arg = arg->next;
-    }
-    if (!base)
-      base = next = cpy_nonext(env, curr);
-    else if(next) { // check me (added after a fuzzing session)
-      next->next = cpy_nonext(env, curr);
-      next       = next->next;
-    }
-  } while ((fn = fn->next));
-  assert(base);
-  if (arg) {
-    free_exp(mp, base);
-    ERR_O(arg->pos, "too many arguments for holes");
-  }
-  return base;
-}
-
-static OP_CHECK(opck_apms) {
-  Exp_Binary *bin  = (Exp_Binary *)data;
-  Exp         lhs  = bin->lhs;
-  Exp_Call    base = bin->rhs->d.exp_call;
-  DECL_ON(const Exp, args, = order_apms(env, base.args, lhs));
-  Exp_Call call = {.func = base.func, .args = args};
-  Exp      e    = exp_self(bin);
-  e->exp_type   = ae_exp_call;
-  e->type       = NULL;
-  memcpy(&e->d.exp_call, &call, sizeof(Exp_Call));
-
-  const MemPool mp = env->gwion->mp;
-  free_exp(mp, base.args);
-  free_exp(mp, lhs);
-
-  return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_error];
-}
-
 static inline void fptr_instr(const Emitter emit, const Func f,
                               const m_uint i) {
   const Instr set = emit_add_instr(emit, RegSetImm);
@@ -354,10 +305,11 @@ ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
   return check_lambda(env, actual_type(env->gwion, info->rhs->value_ref->type), l);
 }
 
-ANN static Type curry2auto(const Env env, const Exp_Binary *bin) {
+ANN static Type partial2auto(const Env env, const Exp_Binary *bin) {
   const Func_Def fdef = bin->lhs->d.exp_lambda.def;
   unset_fbflag(fdef->base, fbflag_lambda);
   CHECK_BN(traverse_func_def(env, fdef));
+  set_fbflag(fdef->base, fbflag_lambda);
   const Type actual = fdef->base->func->value_ref->type;
   set_fbflag(fdef->base, fbflag_lambda);
   Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
@@ -374,7 +326,7 @@ static OP_CHECK(opck_auto_fptr) {
   if (bin->lhs->exp_type == ae_exp_td)
     ERR_N(bin->lhs->pos, "can't use {/}type decl expressions{0} in auto function pointer declarations");
   if(!bin->lhs->type->info->func)
-    return curry2auto(env, bin);
+    return partial2auto(env, bin);
   // create a matching signature
   // TODO: we could check first if there a matching existing one
   Func_Base *const fbase =
@@ -723,18 +675,12 @@ GWION_IMPORT(func) {
   GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@function", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_func_call))
   GWI_BB(gwi_oper_end(gwi, "=>", NULL))
-  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@apms", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_apms))
-  GWI_BB(gwi_oper_end(gwi, "=>", NULL))
   GWI_BB(gwi_oper_ini(gwi, NULL, "@func_ptr", "bool"))
   GWI_BB(gwi_oper_end(gwi, "!", IntNot))
   GWI_BB(gwi_oper_ini(gwi, "@function", "@func_ptr", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_fptr_at))
   GWI_BB(gwi_oper_emi(gwi, opem_func_assign))
   GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
-  //  GWI_BB(gwi_oper_add(gwi, opck_fptr_cast))
-  //  GWI_BB(gwi_oper_emi(gwi, opem_fptr_cast))
-  //  GWI_BB(gwi_oper_end(gwi, "$", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_fptr_impl))
   GWI_BB(gwi_oper_emi(gwi, opem_fptr_impl))
   GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
index 1a0a5f4f75a927050376063e66cb0c1e8cdf7f87..1811e9dcdf891adad55ee0406804c4babca8c0ce 100644 (file)
@@ -44,7 +44,6 @@ int main(int argc, char **argv) {
   CliArg arg = {.arg = {.argc = argc, .argv = argv}, .loop = false};
   signal(SIGINT, sig);
   signal(SIGTERM, sig);
-  struct Gwion_ gwion = {};
   const m_bool  ini   = gwion_ini(&gwion, &arg);
   arg_release(&arg);
   if (ini > 0) gwion_run(&gwion);
index 76697b57022487ef9c621be34439b5b51fbf8a24..46a713a67204446efa02bed2f1e75767f6b334aa 100644 (file)
@@ -14,6 +14,7 @@
 #include "match.h"
 #include "specialid.h"
 #include "tmp_resolve.h"
+#include "partial.h"
 
 ANN static m_bool check_stmt_list(const Env env, Stmt_List list);
 ANN m_bool        check_class_def(const Env env, const Class_Def class_def);
@@ -310,6 +311,9 @@ ANN static Value check_non_res_value(const Env env, const Symbol *data) {
       ERR_O(prim_pos(data),
             _("non-global variable '%s' used from global function/class."),
             s_name(var))
+  } else if(env->func && fbflag(env->func->def->base, fbflag_locale)) {
+    if(!is_func(env->gwion, value->type) && value->from->owner && !from_global_nspc(env, value->from->owner))
+      ERR_O(prim_pos(data), _("invalid variable access from locale definition"));
   }
   return value;
 }
@@ -422,7 +426,7 @@ ANN static Type check_prim_hack(const Env env, const Exp *data) {
 }
 
 ANN static Type check_prim_locale(const Env env, const Symbol *data NUSED) {
-  return env->context->locale->def->base->ret_type;
+  return env->gwion->type[et_float];
 }
 
 #define describe_prim_xxx(name, type)                                          \
@@ -494,14 +498,6 @@ ANN static Type_Decl* mk_td(const Env env, const Arg *arg,
   return type2td(env->gwion, t, pos);
 }
 
-ANN static inline bool func_match_inner(const Env env, const Exp e,
-                                        const Type t, const bool implicit,
-                                        const bool specific) {
-  if (specific ? e->type == t : isa(e->type, t) > 0) // match
-    return true;
-  return !implicit ? false : check_implicit(env, e, t) > 0;
-}
-
 ANN2(1, 2)
 static Func find_func_match_actual(const Env env, Func func, const Exp exp,
                                    const bool implicit, const bool specific) {
@@ -514,7 +510,6 @@ static Func find_func_match_actual(const Env env, Func func, const Exp exp,
       e->cast_to = NULL;
       if (!e->type) // investigate
         return NULL;
-// rewrite
       Arg *arg = i < args_len ? mp_vector_at(args, Arg, i++) : NULL;
       if (!arg) {
         if (fbflag(func->def->base, fbflag_variadic)) return func;
@@ -621,16 +616,6 @@ ANN static void print_current_args(Exp e) {
   gw_err("\n");
 }
 
-ANN static void print_arg(Arg_List args) {
-  for(uint32_t i = 0; i < args->len; i++) {
-    Arg *arg = mp_vector_at(args, Arg, i);
-    gw_err("{G}%s{0} {/}%s{0}", arg->type ? arg->type->name : NULL,
-           arg->var_decl.xid ? s_name(arg->var_decl.xid) : "");
-    if(i < args->len - 1) gw_err(", ");
-  }
-//  while ((e = next_arg_Arg_List(e)));
-}
-
 ANN2(1)
 static void function_alternative(const Env env, const Type f, const Exp args,
                                  const loc_t pos) {
@@ -639,15 +624,8 @@ static void function_alternative(const Env env, const Type f, const Exp args,
   gwerr_basic("Argument type mismatch", "call site",
               "valid alternatives:", env->name, pos, 0);
   Func up = f->info->func;
-  do {
-    gw_err("  {-}(%s){0}  ", up->name);
-    const Arg_List e = up->def->base->args;
-    if (e)
-      print_arg(e);
-    else
-      gw_err("{G}void{0}");
-    gw_err("\n");
-  } while ((up = up->next));
+  do print_signature(up);
+  while ((up = up->next));
   if (args)
     print_current_args(args);
   else
@@ -765,17 +743,6 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
   }
   if(e)
      ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda"))
-/*
-  while (arg && e) {
-    arg->type = e->type;
-    if(is_class(env->gwion, arg->type))
-      type_addref(arg->type);
-    arg       = arg->next;
-    e         = e->next;
-  }
-  if (arg || e)
-    ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda"))
-*/
   l->def->base->values = env->curr->info->value;
   const m_bool ret     = traverse_func_def(env, l->def);
   if (l->def->base->func) {
@@ -867,10 +834,13 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
       }
     exp->func->type = func->value_ref->type;
     call_add_effect(env, func, exp->func->pos);
-//    if (func == env->func) set_fflag(env->func, fflag_recurs);
     return func->def->base->ret_type != env->gwion->type[et_auto] ?
       func->def->base->ret_type : exp->func->d.exp_dot.base->type;
   }
+  if(exp->func->exp_type == ae_exp_lambda) {
+    const Type tt = partial_type(env, exp);
+    if(tt) return tt;
+  }
   function_alternative(env, exp->func->type, exp->args, exp->func->pos);
   return NULL;
 }
@@ -884,7 +854,6 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) {
   CHECK_OO(check_exp(env, bin->rhs));
   if (is_auto) {
     assert(bin->rhs->type == bin->lhs->type);
-//    bin->rhs->type = bin->lhs->type;
     set_vflag(mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0)->value, vflag_assigned);
   }
   struct Op_Import opi = {.op   = bin->op,
@@ -938,9 +907,9 @@ ANN static m_bool predefined_call(const Env env, const Type t,
   return GW_ERROR;
 }
 
-ANN2(1) static inline bool apms(const Env env, Exp exp) {
+ANN2(1) static inline bool is_partial(const Env env, Exp exp) {
   while (exp) {
-    if (is_hole(env, exp))
+    if (is_hole(env, exp) || is_typed_hole(env, exp))
       return true;
     exp = exp->next;
   }
@@ -968,8 +937,10 @@ ANN static Type check_exp_call_tmpl(const Env env, Exp_Call *exp, const Type t)
 }
 
 ANN static Type check_exp_call(const Env env, Exp_Call *exp) {
-  if (exp->apms && apms(env, exp->args))
-    return env->gwion->type[et_apms];
+  if (is_partial(env, exp->args)) {
+    CHECK_OO(check_exp(env, exp->func));
+    return partial_type(env, exp);
+  }
   if (exp->tmpl) {
     DECL_BO(const m_bool, ret, = func_check(env, exp));
     if (!ret) return exp_self(exp)->type;
@@ -1345,6 +1316,13 @@ ANN m_bool check_union_def(const Env env NUSED, const Union_Def udef) {
 }
 
 ANN static m_bool check_stmt_exp(const Env env, const Stmt_Exp stmt) {
+  if(stmt->val) {
+    CHECK_OB(check_exp(env, stmt->val));
+    if(stmt->val->exp_type == ae_exp_lambda) {
+     const loc_t loc = stmt->val->d.exp_lambda.def->base->pos;
+     env_warn(env, loc, _("Partial application not used"));
+    }
+  }
   return stmt->val ? check_exp(env, stmt->val) ? 1 : -1 : 1;
 }
 
@@ -1500,9 +1478,19 @@ ANN static m_bool check_stmt_match(const Env env, const Stmt_Match stmt) {
 ANN static m_bool check_stmt_pp(const Env env, const Stmt_PP stmt) {
   if (stmt->pp_type == ae_pp_include) env->name = stmt->data;
   // check for memoization
-  if (env->func && stmt->pp_type == ae_pp_pragma &&
+  else if (env->func && stmt->pp_type == ae_pp_pragma &&
       !strncmp(stmt->data, "memoize", strlen("memoize")))
     env->func->memoize = strtol(stmt->data + 7, NULL, 10);
+  else if(stmt->pp_type == ae_pp_locale) {
+    const loc_t loc = stmt_self(stmt)->pos;
+    const Exp id   = new_prim_id(env->gwion->mp, stmt->xid, loc);
+    const Exp arg   = new_prim_id(env->gwion->mp, insert_symbol("_"), loc);
+    arg->next = stmt->exp;
+    const Exp call = new_exp_call(env->gwion->mp, id, arg, loc);
+    stmt->exp = call;
+    CHECK_BB(traverse_exp(env, id));
+    CHECK_OB(partial_type(env, &call->d.exp_call));
+  }
   return GW_OK;
 }
 
@@ -1673,7 +1661,7 @@ ANN m_bool _check_func_def(const Env env, const Func_Def f) {
   if(fflag(func, fflag_valid))return GW_OK;
   set_fflag(func, fflag_valid);
   assert(func == fdef->base->func);
-  if (env->class_def && !strstr(func->name, "lambda:"))
+  if (env->class_def && !fbflag(func->def->base, fbflag_lambda))
     CHECK_BB(check_parent_match(env, fdef));
   if (tmpl_base(fdef->base->tmpl)) return GW_OK;
   Value override = NULL;
diff --git a/src/parse/partial.c b/src/parse/partial.c
new file mode 100644 (file)
index 0000000..85aab19
--- /dev/null
@@ -0,0 +1,211 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "instr.h"
+#include "emit.h"
+#include "gwion.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "traverse.h"
+#include "parse.h"
+#include "partial.h"
+
+ANN static Arg_List partial_arg_list(const Env env, const Arg_List base, const Exp e) {
+  Arg_List args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0);
+  Exp next = e;
+  uint32_t i = 0;
+  while(next) {
+    if(is_hole(env, next) || is_typed_hole(env, next)) {
+      char c[256];
+      sprintf(c, "@%u", args->len);
+      const Arg *src = mp_vector_at(base, Arg, i);
+      Type_Decl *td = src->td ? cpy_type_decl(env->gwion->mp, src->td) : NULL;
+      Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c) }};
+      mp_vector_add(env->gwion->mp, &args, Arg, arg);
+    }
+    i++;
+    next = next->next;
+  }
+  return args;
+}
+
+ANN static inline Symbol partial_name(const Env env, const pos_t pos) {
+  char c[7 + 1 + num_digit(pos.line) + num_digit(pos.column) + 2];
+  sprintf(c, "partial:%u:%u", pos.line, pos.column);
+  return insert_symbol(c);
+}
+
+ANN2(1, 2) static inline Func_Base *partial_base(const Env env, const Func_Base *base, Exp earg, const loc_t loc) {
+  Arg_List args = earg ? partial_arg_list(env, base->args, earg) : NULL;
+  Func_Base *fb = new_func_base(env->gwion->mp, cpy_type_decl(env->gwion->mp, base->td), partial_name(env, loc.first), args, ae_flag_none, loc);
+  return fb;
+}
+
+ANN static Exp partial_call(const Env env, Exp e) {
+  Exp base = NULL, arg;
+  uint32_t i = 0;
+  while(e) {
+    if(is_hole(env, e) || is_typed_hole(env, e)) {
+      char c[256];
+      sprintf(c, "@%u", i++);
+      const Exp next = new_prim_id(env->gwion->mp, insert_symbol(c), e->pos);
+      if(base) arg = arg->next = next;
+      else arg = base = next;
+    } else {
+      const Exp next = cpy_exp(env->gwion->mp, e);
+      if(base) arg = arg->next = next;
+      else arg = base = next;
+    }
+    e = e->next;
+  }
+  return base;
+}
+
+
+ANN Func find_match(const Env env, Func func, const Exp exp, const bool implicit,
+                                        const bool specific) {
+  do {
+    Exp e = exp;
+    uint32_t i = 0;
+    Arg_List args = func->def->base->args;
+    uint32_t len = args ? args->len : 0;
+    while(e) {
+      if (i >= len) break;
+      const Arg *arg = mp_vector_at(args, Arg, i++);
+      if(!is_hole(env, e)) {
+        if(!is_typed_hole(env, e)) {
+          const Exp next = e->next;
+          e->next = NULL;
+          check_exp(env, e);
+          e->next = next;
+      } else
+          CHECK_OO((e->type = known_type(env, e->d.exp_cast.td)));
+        if (!func_match_inner(env, e, arg->type, implicit, specific)) break;
+      }
+      e = e->next;
+    }
+    if (!e && len == i) return func;
+  } while ((func = func->next));
+  return NULL;
+}
+
+ANN Func find_match_actual(const Env env, const Func up, const Exp args) {
+  Func func;
+  if ((func = find_match(env, up, args, false, true)) ||
+      (func = find_match(env, up, args, true, true)) ||
+      (func = find_match(env, up, args, false, true)) ||
+      (func = find_match(env, up, args, true, false)))
+    return func;
+  return NULL;
+}
+
+ANN static Func partial_match(const Env env, const Func up, const Exp args, const loc_t loc);
+
+ANN static void print_arg(Arg_List args) {
+  for(uint32_t i = 0; i < args->len; i++) {
+    Arg *arg = mp_vector_at(args, Arg, i);
+    gw_err("{G}%s{0} {/}%s{0}", arg->type ? arg->type->name : NULL,
+           arg->var_decl.xid ? s_name(arg->var_decl.xid) : "");
+    if(i < args->len - 1) gw_err(", ");
+  }
+}
+
+ANN void print_signature(const Func f) {
+  gw_err("  {-}(%s){0}  ", f->name);
+  const Arg_List args = f->def->base->args;
+  if (args)
+    print_arg(args);
+  else
+    gw_err("{G}void{0}");
+  gw_err("\n");
+}
+
+ANN void ambiguity(const Env env, Func f, const Exp args, const loc_t loc) {
+  print_signature(f);
+  while(f->next) {
+    const Func next = partial_match(env, f->next, args, loc);
+    if(next) print_signature(next);
+    f = f->next;
+  }
+}
+
+ANN static Func partial_match(const Env env, const Func up, const Exp args, const loc_t loc) {
+  const Func f = find_match_actual(env, up, args);
+  if(f) {
+    if(f->next) {
+      const Func next = partial_match(env, f->next, args, loc);
+      if(next) {
+        gwerr_basic(_("can't resolve ambiguity"), _("in this partial application"), _("use typed holes: _ $ type"), env->name, loc, 0);
+        gw_err(_("\nthose functions could match:\n"));
+        print_signature(f);
+        ambiguity(env, next, args, loc);
+        env->context->error = true;
+        return NULL;
+      }
+    }
+    return f;
+  }
+  return NULL;
+}
+
+ANN static Stmt partial_code(const Env env, const Exp efun, const Exp earg) {
+  Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
+  const Exp arg = partial_call(env, earg);
+  const Exp exp = new_exp_call(env->gwion->mp, efun, arg, efun->pos);
+  Stmt stmt = mp_vector_at(slist, struct Stmt_, 0);
+  stmt->stmt_type = ae_stmt_return;
+  stmt->d.stmt_exp.val = exp;
+  return new_stmt_code(env->gwion->mp, slist, efun->pos);
+}
+
+ANN static uint32_t count_args_exp(Exp args) {
+  uint32_t i = 0;
+  while(args && ++i) args = args->next;
+  return i;
+}
+
+ANN static uint32_t count_args_func(Func f, const uint32_t i) {
+  uint32_t max = 0;
+  while(f) {
+    const uint32_t len =  f->def->base->args ? f->def->base->args->len : 0;
+    if(len > i && len > max) max = len;
+    f = f->next;
+  }
+  return max;
+}
+
+ANN static Exp expand(const Env env, const Func func, const Exp e, const loc_t loc) {
+  const uint32_t i = count_args_exp(e);
+  const uint32_t max = count_args_func(func, i);
+  if(max > i) {
+    Exp args = e;
+    if(args) {
+      while(args->next) args = args->next;
+      args->next = new_prim_id(env->gwion->mp, insert_symbol("_"), loc);
+      return e;
+    } else return new_prim_id(env->gwion->mp, insert_symbol("_"), loc);
+  }
+  return NULL;
+}
+
+ANN Type partial_type(const Env env, Exp_Call *const call) {
+  const Func f = partial_match(env, call->func->type->info->func, call->args, call->func->pos);
+  if(!f) {
+    const Exp e = expand(env, call->func->type->info->func, call->args, call->func->pos);
+    if(e) {
+      call->args = e;
+      return partial_type(env, call);
+    }
+    ERR_O(call->func->pos, _("no match found for partial application"));
+  }
+  Func_Base *const base = partial_base(env, f->def->base, call->args, call->func->pos);
+  const Stmt code = partial_code(env, call->func, call->args);
+  const Exp exp = exp_self(call);
+  exp->d.exp_lambda.def = new_func_def(env->gwion->mp, base, code);
+  exp->exp_type = ae_exp_lambda;
+  CHECK_OO(traverse_func_def(env, exp->d.exp_lambda.def));
+  return exp->d.exp_lambda.def->base->func->value_ref->type;
+}
index b8a9f0474d533a2e6f709fa2fd7b882392341a7b..ff31b0019f3b0bd37434f702988068cb13aeb4c0 100644 (file)
@@ -54,7 +54,8 @@ ANN static m_bool scan2_args(const Func_Def f) {
     Arg *arg = mp_vector_at(args, Arg, i);
     const Value v   = arg->var_decl.value;
     v->from->offset = f->stack_depth;
-    f->stack_depth += v->type->size;
+    //f->stack_depth += v->type->size;
+    f->stack_depth += v->type ? v->type->size : SZ_INT;
     if (global) SET_FLAG(v, global);
   }
   return GW_OK;
@@ -146,7 +147,6 @@ ANN static inline m_bool scan2_exp_binary(const Env         env,
                                           const Exp_Binary *bin) {
   CHECK_BB(scan2_exp(env, bin->lhs));
   CHECK_BB(scan2_exp(env, bin->rhs));
-  if(bin->rhs->exp_type == ae_exp_call)bin->rhs->d.exp_call.apms = true;
   CHECK_BB(multi_decl(env, bin->lhs, bin->op));
   return multi_decl(env, bin->rhs, bin->op);
 }
index 69d3d53cc363cdf6fc48c26f8d2d0300fe1dca04..3cb6fcd1797448fd613b637efa6c9ca562ddd932 100644 (file)
@@ -132,8 +132,8 @@ ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
     Specialized_List    sl = t->info->cdef->base.tmpl
         ? t->info->cdef->base.tmpl->list : NULL;
     for(uint32_t i = 0; i < tl->len; i++) {
-      Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
-      DECL_OO(const Type, t, = known_type(env, td));
+      Type_Decl *tmp = *mp_vector_at(tl, Type_Decl*, i);
+      DECL_OO(const Type, t, = known_type(env, tmp));
         Specialized *spec = mp_vector_at(sl, Specialized, i);
         if(spec->traits) {
           Symbol missing = miss_traits(t, spec);
diff --git a/tests/locale/locale.basic.gw b/tests/locale/locale.basic.gw
new file mode 100644 (file)
index 0000000..4d4b4ee
--- /dev/null
@@ -0,0 +1,3 @@
+#! [contains] 440
+
+<<< `A4` >>>;
diff --git a/tests/locale/locale_default_args.gw b/tests/locale/locale_default_args.gw
new file mode 100644 (file)
index 0000000..2272ce0
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] 432
+locale Test(float base : 432) { return base; }
+
+#locale Test
+<<< `foo` >>>;
diff --git a/tests/locale/locale_with_args.gw b/tests/locale/locale_with_args.gw
new file mode 100644 (file)
index 0000000..3977e71
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] 440
+locale Test(float base : 432) { return base; }
+
+#locale Test 440
+<<< `foo` >>>;
similarity index 100%
rename from tests/apms/apms1.gw
rename to tests/partial/apms1.gw
similarity index 100%
rename from tests/apms/apms2.gw
rename to tests/partial/apms2.gw
similarity index 100%
rename from tests/apms/apms3.gw
rename to tests/partial/apms3.gw
diff --git a/tests/partial/partial_ambiguous.gw b/tests/partial/partial_ambiguous.gw
new file mode 100644 (file)
index 0000000..3a273dd
--- /dev/null
@@ -0,0 +1,4 @@
+#! [contains] can't resolve ambiguity
+fun void test(int i, int j) {}
+fun void test(int i, string s) {}
+test(_, _);
diff --git a/tests/partial/partial_no_match.gw b/tests/partial/partial_no_match.gw
new file mode 100644 (file)
index 0000000..8daa922
--- /dev/null
@@ -0,0 +1,3 @@
+#! [contains] no match found for partial application
+fun void test(int i) {}
+test(_, _);
diff --git a/tests/partial/partial_not_used.gw b/tests/partial/partial_not_used.gw
new file mode 100644 (file)
index 0000000..936be2b
--- /dev/null
@@ -0,0 +1,2 @@
+#! [contains] Partial application not used
+me.arg(_);
diff --git a/util b/util
index 34744e7349965d104709563bba8861fadf544bd1..2b55ce354595c33d5cee4a90085feb2a31be1572 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 34744e7349965d104709563bba8861fadf544bd1
+Subproject commit 2b55ce354595c33d5cee4a90085feb2a31be1572