diff options
Diffstat (limited to '')
| -rw-r--r-- | Changelog.md | 30 | ||||
| -rw-r--r-- | Gentle_introduction_Inpla.md | 30 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/id_table.c | 4 | ||||
| -rw-r--r-- | src/id_table.h | 3 | ||||
| -rw-r--r-- | src/inpla.y | 91 |
6 files changed, 141 insertions, 19 deletions
diff --git a/Changelog.md b/Changelog.md index f6cc0dc..834f565 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,35 @@ # Change log +### v0.9.2 (released on 30 July 2022) +#### New Features +* **A built-in agent** `Map`: Map function operation is realised by the following definition: +e + ``` + Map(result, f) >< [] => result~[], Eraser~f; + Map(result, f) >< x:xs => Dup(f1,f2)~f, + result~w:ws, + f1 ~ (w, x), Map(ws, f2)~xs; + ``` + Now, the Map has been implemented as built-in. + ``` + >>> inc(r)><(int i)=>r~i+1; + >>> Map(r1, (r, inc(r))) ~ [1,2,3]; + (22 interactions, 0.00 sec) + >>> r1; + [2,3,4] + >>> Map(r2, (r, Add(r,10))) ~ [1,2,3]; + (26 interactions, 0.00 sec) + >>> r2; + [11,12,13] + >>> Map(r3, %inc) ~ [1,2,3]; + (12 interactions, 0.00 sec) + >>> r3; + [2,3,4] + >>> + ``` + + + ### v0.9.1 (released on 28 July 2022) #### New Features * **A built-in agent** `Zip`: It takes two lists and returns a list whose elements are pairs of the given two lists elements such that: diff --git a/Gentle_introduction_Inpla.md b/Gentle_introduction_Inpla.md index 0903a6f..e2617d1 100644 --- a/Gentle_introduction_Inpla.md +++ b/Gentle_introduction_Inpla.md @@ -688,31 +688,31 @@ it merges two lists into one. Merger agent has two principal ports that can take ``` ### Map and reduce functions -* **Lambda and Application like computation**: We can leave an interaction later by using a couple of Tuple2 agents. For instance, an destructor agent `foo` whose arity is 1 can be abstracted as `(r, foo(r))`, and we can give a constructor `s` later: +* **Lambda-application-like computation**: We can leave an interaction later by using a couple of Tuple2 agents. For instance, an destructor agent `foo` whose arity is 1 can be abstracted as `(r, foo(r))`, and we can give a constructor `s` later: ``` (r, foo(r)) >< (result, s) -->* foo(result)~s. // where the following rule has been defined as a built-in: // (a1,a2) ><> (b1,b2) => a1~b1, a2~b2. ``` - So, the map function can be realised: +* **Map function operation**: So, the map function operation can be realised by a built-in `Map` agent with the following already defined rules: ``` - map(result, f) >< [] => result~[], Eraser~f; - map(result, f) >< x:xs => Dup(f1,f2)~f, + Map(result, f) >< [] => result~[], Eraser~f; + Map(result, f) >< x:xs => Dup(f1,f2)~f, result~w:ws, - f1 ~ (w, x), map(ws, f2)~xs; + f1 ~ (w, x), Map(ws, f2)~xs; ``` Actually, by using the incrementor `inc` we can add one to each list element: ``` inc(r)><(int i) => r~(i+1); - map( result, (r,inc(r)) ) ~ [10,20,30] - --> Dup(f1,f2)~(r,inc(r)), result~w:ws, f1~(w,10), map(ws,f2)~[20,30] - -->* result~w:ws, (r1,inc(r1))~(w,10), map( ws, (r2,inc(r2)) )~[20,30] - -->* result~w:ws, inc(w)~10, map( ws, (r2,inc(r2)) )~[20,30] - --> result~w:ws, w~11, map(ws, (r2,inc(r2)) )~[20,30] - --> result~11:ws, map(ws, (r2,inc(r2)) )~[20,30] - -->* result~11:21:ws, map(ws, (r3,inc(r3)) )~[30] - -->* result~11:21:31:ws, map(ws, (r4,inc(r4)) )~[] + Map( result, (r,inc(r)) ) ~ [10,20,30] + --> Dup(f1,f2)~(r,inc(r)), result~w:ws, f1~(w,10), Map(ws,f2)~[20,30] + -->* result~w:ws, (r1,inc(r1))~(w,10), Map( ws, (r2,inc(r2)) )~[20,30] + -->* result~w:ws, inc(w)~10, Map( ws, (r2,inc(r2)) )~[20,30] + --> result~w:ws, w~11, Map(ws, (r2,inc(r2)) )~[20,30] + --> result~11:ws, Map(ws, (r2,inc(r2)) )~[20,30] + -->* result~11:21:ws, Map(ws, (r3,inc(r3)) )~[30] + -->* result~11:21:31:ws, Map(ws, (r4,inc(r4)) )~[] -->* result~[11,21,31]; ``` The Tuple2 agent seems a little complicated, so we prepare an abbreviation `%`. In the following, `foo1`, `foo2`, `foo3`, ... are any agents whose arity is 1, 2, 3, ..., respectively. @@ -731,14 +731,14 @@ it merges two lists into one. Merger agent has two principal ports that can take ``` This is quite useful for the map application. The `inc` application is written simply as follows: ``` - >>> map(result, %inc) ~ [1,2,3]; + >>> Map(result, %inc) ~ [1,2,3]; >>> result; [2,3,4] >>> ``` Wonderful! - The same as the map operation, we can define foldr and foldl as follows (Do not worry if it looks complicated. It is OK if we can just use these!): +* **Reduce function operation**: The same as the map operation, we can define foldr and foldl as follows (Do not worry if it looks complicated. It is OK if we can just use these!): ``` // -------------------------------------------------------------------- // foldr f v [x0, x1, ..., xn] = f(x0, f(x1, ... f(xn-1, f(xn, v))...)) @@ -6,7 +6,7 @@ Inpla is a multi-threaded parallel interpreter of interaction nets. Once you write programs for sequential execution, it works also in multi-threaded parallel execution. Each thread is managed on each CPU-core with POSIX-thread library. -* The current version is 0.9.1, released on **28 July 2022**. (See [Changelog.md](Changelog.md) for details.) +* The current version is 0.9.2, released on **30 July 2022**. (See [Changelog.md](Changelog.md) for details.) * The below graph shows speed-up ratio to threads numbers for programs in the following benchmark table.  diff --git a/src/id_table.c b/src/id_table.c index 2ad96ad..fc22bb1 100644 --- a/src/id_table.c +++ b/src/id_table.c @@ -54,6 +54,7 @@ void IdTable_init() { IdTable[ID_MOD].aux.arity = 2; IdTable[ID_MOD2].aux.arity = 2; IdTable[ID_PERCENT].aux.arity = 1; + IdTable[ID_MAP].aux.arity = 2; IdTable[ID_ERASER].aux.arity = 0; IdTable[ID_DUP].aux.arity = 2; @@ -86,6 +87,7 @@ void IdTable_init() { IdTable[ID_MOD].name = "Mod"; IdTable[ID_MOD2].name = "_Mod"; IdTable[ID_PERCENT].name = "%"; + IdTable[ID_MAP].name = "Map"; IdTable[ID_ERASER].name = "Eraser"; IdTable[ID_DUP].name = "Dup"; @@ -117,6 +119,8 @@ int IdTable_getid_builtin_funcAgent(Ast *agent) { id = ID_APPEND; } else if (strcmp((char *)agent->left->sym, "Zip") == 0) { id = ID_ZIP; + } else if (strcmp((char *)agent->left->sym, "Map") == 0) { + id = ID_MAP; } else if (strcmp((char *)agent->left->sym, "Int") == 0) { id = ID_INTAGENT; } else if (strcmp((char *)agent->left->sym, "Merger") == 0) { diff --git a/src/id_table.h b/src/id_table.h index 7ee04bc..c486975 100644 --- a/src/id_table.h +++ b/src/id_table.h @@ -51,7 +51,8 @@ #define ID_MOD 28 #define ID_MOD2 29 #define ID_PERCENT 30 -#define END_ID_OF_BUILTIN_OP_AGENT 30 +#define ID_MAP 31 +#define END_ID_OF_BUILTIN_OP_AGENT 31 // ID_ERASER and ID_DUP was put as 254, 255 // because these IDs are wanted larger like ID_DUP > any_agent.id diff --git a/src/inpla.y b/src/inpla.y index 182bed7..6053ff1 100644 --- a/src/inpla.y +++ b/src/inpla.y @@ -22,8 +22,8 @@ // ---------------------------------------------- -#define VERSION "0.9.1" -#define BUILT_DATE "28 July 2022" +#define VERSION "0.9.2" +#define BUILT_DATE "30 July 2022" // ------------------------------------------------------------------ @@ -9635,6 +9635,93 @@ loop_agent_a1_a2_this_order: break; // end ID_ZIPC + case ID_MAP: + switch (BASIC(a2)->id) { + case ID_NIL: + { + // Map(result, f) >< [] => result~[], Eraser~f; + COUNTUP_INTERACTION(vm); + + VALUE a1p0 = AGENT(a1)->port[0]; + VALUE a1p1 = AGENT(a1)->port[1]; + + // Eraser + BASIC(a1)->id = ID_ERASER; + PUSH(vm, a1, a1p1); + + a1=a1p0; + goto loop; + } + + case ID_CONS: + { + COUNTUP_INTERACTION(vm); + + VALUE a1p0 = AGENT(a1)->port[0]; + VALUE a1p1 = AGENT(a1)->port[1]; + + VALUE a2p0 = AGENT(a2)->port[0]; + VALUE a2p1 = AGENT(a2)->port[1]; + VALUE w = make_Name(vm); + VALUE ws = make_Name(vm); + + VALUE pair = make_Agent(vm, ID_TUPLE2); + + AGENT(a2)->port[0] = w; + AGENT(a2)->port[1] = ws; + PUSH(vm, a1p0, a2); + + /* + if ((IS_NAMEID(BASIC(a1p1)->id)) + && (NAME(a1p1)->port != NULL)) { + VALUE a1p1_agent = NAME(a1p1)->port; + free_Name(a1p1); + AGENT(a1)->port[1] = a1p1_agent; + } + */ + + if (BASIC(a1p1)->id == ID_PERCENT) { + // special case + //Map(result, %f) >< x:xs => + // result~w:ws, + // %f ~ (w, x), Map(ws, %f)~xs; + + AGENT(pair)->port[0] = w; + AGENT(pair)->port[1] = a2p0; + VALUE new_percent = make_Agent(vm, ID_PERCENT); + AGENT(new_percent)->port[0] = AGENT(a1p1)->port[0]; + PUSH(vm, new_percent, pair); + + AGENT(a1)->port[0] = ws; + a2 = a2p1; + goto loop; + } + + // Map(result, f) >< x:xs => Dup(f1,f2)~f, + // result~w:ws, + // f1 ~ (w, x), map(ws, f2)~xs; + + VALUE dup = make_Agent(vm, ID_DUP); + VALUE f1 = make_Name(vm); + VALUE f2 = make_Name(vm); + AGENT(dup)->port[0] = f1; + AGENT(dup)->port[1] = f2; + PUSH(vm, dup, a1p1); + + AGENT(pair)->port[0] = w; + AGENT(pair)->port[1] = a2p0; + PUSH(vm, f1, pair); + + AGENT(a1)->port[0] = ws; + AGENT(a1)->port[1] = f2; + a2 = a2p1; + goto loop; + + } + } + + break; // end ID_MAP + case ID_MERGER: switch (BASIC(a2)->id) { |
