diff options
| author | Shinya Sato <shinnya.sato@gmail.com> | 2021-10-29 01:35:54 +0900 |
|---|---|---|
| committer | Shinya Sato <shinnya.sato@gmail.com> | 2021-10-29 01:35:54 +0900 |
| commit | d28e80274828540a3278ef20c3250afb576773d4 (patch) | |
| tree | 329944a21b8dc12653e2b3105fb8264df1fb3fad | |
| parent | 8b6cf5aa982859035c015c95f31e989add9af238 (diff) | |
| download | inpla-d28e80274828540a3278ef20c3250afb576773d4.tar.gz inpla-d28e80274828540a3278ef20c3250afb576773d4.zip | |
v0.5.0
Diffstat (limited to '')
| -rw-r--r-- | Changelog.md | 63 | ||||
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | README.md | 116 | ||||
| -rw-r--r-- | pic/merger.png | bin | 0 -> 16448 bytes | |||
| -rw-r--r-- | sample/245II_abbr.in | 98 | ||||
| -rw-r--r-- | sample/fib_9.in | 2 | ||||
| -rw-r--r-- | sample/fib_9_abbr.in | 16 | ||||
| -rw-r--r-- | sample/linear-systemT.in | 8 | ||||
| -rw-r--r-- | sample/processnet1.in | 2 | ||||
| -rw-r--r-- | sample/processnet_fib.in | 30 | ||||
| -rw-r--r-- | src/ast.c | 92 | ||||
| -rw-r--r-- | src/ast.h | 6 | ||||
| -rw-r--r-- | src/id_table.c | 69 | ||||
| -rw-r--r-- | src/id_table.h | 29 | ||||
| -rw-r--r-- | src/inpla.l | 16 | ||||
| -rw-r--r-- | src/inpla.y | 432 | ||||
| -rw-r--r-- | src/linenoise/.gitignore | 3 | ||||
| -rw-r--r-- | src/name_table.c | 2 | ||||
| -rw-r--r-- | src/name_table.h | 2 |
19 files changed, 781 insertions, 210 deletions
diff --git a/Changelog.md b/Changelog.md index 5919b0c..7016c24 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,22 +1,61 @@ # Changelog -## v0.4.2 (16 October 2021) +## v0.5.0 (released 28 October 2021) +### New features: +- **Abbreviation notation**: An abbreviation notation `<<` is introduced. The following description: -### Improved + ``` + a,b,...,z << Agent(aa,bb,...,yy,zz) + ``` -- Line edit was improved to support multi-line paste, according to the following suggestion: - https://github.com/antirez/linenoise/issues/43 + is rewritten internally as follows: -- History in Line edit becomes available. + ``` + Agent(a,b,...,z,aa,bb,...,yy) ~ zz + ``` + For instance, `r << Add(1,2)` is rewritten internally as `Add(r,1)~2`. It is handy to denote ports that take computation results. As a special case we prepare a built-in abbreviation for the built-in agent `Append(a,b)` because the order of those arguments `a`, `b` is different from the abbreviation rewriting rule: -### Bug Fix -- Long length lists are printed out as abbreviation of 14-length lists, -though these were printed out as 1-length lists after putting long lists. + ``` + ret << Append(a,b) --- rewritten as ---> Append(ret,b)~a + ``` + +- **Merger agent that merges two lists into one**: Merger agent is implemented, such that it has two principal ports for the two lists, and whose interactions are performed as soon as one of the principal ports is ready for the interaction, that is to say, connected to a list. So, the merged result is decided non-deterministically, especially in multi-threaded execution. + +  + + We overload `<<` in order to use the Merger agent naturally as follows: + + ``` + ret << Merger(alist, blist) + ``` + +- **Built-in rules for arithmetic operations between two agents**: These are implemented, and these operations are managed agents `Sub`, `Mul`, `Div`, `Mod`: + + ``` + >>> r1 << Add(3,5), r2 << Sub(r1,2); + >>> ifce; // put all interface (living names) and connected nets. + r2 + + Connections: + r2 ->6 + + >>> + ``` + + + +- ## v0.4.2 (released 16 October 2021) + ### Improved + - Line edit was improved to support multi-line paste, according to the following suggestion: https://github.com/antirez/linenoise/issues/43 + - History in Line edit becomes available. + + ### Bug Fix + - Long length lists are printed out as abbreviation of 14-length lists, though these were printed out as 1-length lists after putting long lists. -## v0.4.1 (24 September 2021) +## v0.4.1 (released 24 September 2021) ### Improved @@ -35,7 +74,7 @@ though these were printed out as 1-length lists after putting long lists. -## v0.4.0 (17 September 2021) +## v0.4.0 (released 17 September 2021) ### New Feature: @@ -64,7 +103,7 @@ though these were printed out as 1-length lists after putting long lists. -## v0.3.2 (3 August 2021) +## v0.3.2 (released 3 August 2021) ### New Feature: @@ -92,7 +131,7 @@ though these were printed out as 1-length lists after putting long lists. -## v0.3.1 (7 May 2021) +## v0.3.1 (released 7 May 2021) ### New Feature: @@ -1,11 +1,10 @@ CC = gcc -CFLAGS = -Wall -Winline -O3 -std=gnu99 --param inline-unit-growth=2000 --param max-inline-insns-single=2000 +CFLAGS = -Wall -Winline -O3 -std=gnu99 --param inline-unit-growth=1000 --param max-inline-insns-single=1200 LDFLAGS = LIBS = INCLUDE = -I ./src SRC_DIR = ./src OBJ_DIR = ./build -#SOURCES = $(SRC_DIR)/ast.c $(SRC_DIR)/id_table.c $(SRC_DIR)/linenoise/linenoise.c TARGET = inpla OBJS = $(OBJ_DIR)/$(TARGET).tab.c $(OBJ_DIR)/ast.o $(OBJ_DIR)/id_table.o $(OBJ_DIR)/linenoise.o @@ -41,7 +40,7 @@ $(OBJ_DIR): fi clean: - rm -f $(TARGET)* $(OBJ_DIR)/* *stackdump* + rm -f $(TARGET)* $(OBJ_DIR)/* *stackdump* *core* @if [ -f $(SRC_DIR)/linenoise/linenoise.c.orig ]; then \ echo "mv -f $(SRC_DIR)/linenoise/linenoise.c.orig $(SRC_DIR)/linenoise/linenoise.c"; \ mv -f $(SRC_DIR)/linenoise/linenoise.c.orig $(SRC_DIR)/linenoise/linenoise.c; \ @@ -19,23 +19,74 @@ Inpla is a multi-threaded parallel interpreter of interaction nets. Once you wri - **Comparison in execution time** with other implementations: **Haskell** (GHC version 8.10.7), **Standard ML** v110.74 (interpreter mode) and **Python** 3.8.5 in execution time. - The above table contains execution time in second on average of ten times execution by using Linux PC (Core i7-9700 (8 threads, no Hyper-threading), 16GB memory). The fastest one is shown with bold style. These scripts are stored in the `comparison` directory. + - Inpla*n* and Inpla*n*_**r** mean *n* threads without/with reuse-annotated execution, respectively. + - "ack(3,11)" is computation of Ackermann function. Execution time of Python is a blank due to stack size limitation error. + - "fib 38" is computation to get the 38th Fibonacci number. + - "bsort *n*", "isort *n*", "qsort *n*" and "msort *n*" are computation of bubble sort, insertion sort, quick sort and merge sort for random *n*-element lists, respectively. + + +### Feature of Version 0.5.0 (released on 28 October 2021) +- **Abbreviation notation**: An abbreviation notation `<<` is introduced. The following description: + ``` + a,b,...,z << Agent(aa,bb,...,yy,zz) + ``` -### Feature of Version 0.4.2 -- Line edit supports multi-line inputs. + is rewritten internally as follows: -### Feature of Version 0.4.1 -- Integer numbers can be written the same as one of the first-class objects. -- Interaction rules can re-allocate heaps of the rule agents to agents in nets. This re-allocation is specified by modifications such as (\*L), (\*R), called reuse annotation [1], to agents in nets. This re-allocation can improve execution performance in parallel. This is experimental, thus in future version these should be decided automatically, so please do not care so much. -- Weak reduction strategy is supported. It turns on by invoked with ```-w``` option, and then only connections that have living names are evaluated. -- Nested guards in conditional rules are supporeted. + ``` + Agent(a,b,...,z,aa,bb,...,yy) ~ zz + ``` + + For instance, `r << Add(1,2)` is rewritten internally as `Add(r,1)~2`. It is handy to denote ports that take computation results. As a special case we prepare a built-in abbreviation for the built-in agent `Append(a,b)` because the order of those arguments `a`, `b` is different from the abbreviation rewriting rule: + + ``` + ret << Append(a,b) --- rewritten as ---> Append(ret,b)~a + ``` +- **Merger agent that merges two lists into one**: Merger agent is implemented, such that it has two principal ports for the two lists, and whose interactions are performed as soon as one of the principal ports is ready for the interaction, that is to say, connected to a list. So, the merged result is decided non-deterministically, especially in multi-threaded execution. + +  + + We overload `<<` in order to use the Merger agent naturally as follows: + ``` + ret << Merger(alist, blist) + ``` + + The following is an execution example (the count of interactions is not supported yet): + ``` + >>> r << Merger([0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1]); + (1 interactions by 4 threads, 0.10 sec) + >>> ifce; + r + + Connections: + r ->[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0] + + >>> + ``` + + +- **Built-in rules for arithmetic operations between two agents**: These are implemented, and these operations are managed agents `Sub`, `Mul`, `Div`, `Mod`: + + ``` + >>> r1 << Add(3,5), r2 << Sub(r1,2); + >>> ifce; // put all interface (living names) and connected nets. + r2 + + Connections: + r2 ->6 + + >>> + ``` + + ## Getting started - Requirement @@ -61,12 +112,12 @@ $ make thread ``` $ ./inpla - Inpla 0.4.1 : Interaction nets as a programming language [built: 21 Sept. 2021] + Inpla 0.5.0 : Interaction nets as a programming language [built: 28 Oct. 2021] >>> ``` -- The symbol `>>>` is a prompt of Inpla. After the prompt you can write rules and nets. For instance, the following is a rule for incrementation `inc` and a net to bind the increment result of `10` to a name `r` (`//` is a comment): +- The symbol `>>>` is a prompt of Inpla. After the prompt you can write rules and nets. For instance, the following is a rule for incrementation `inc` and a net to bind the increment result of `10` to a name `r` (where `//` is a comment): ``` >>> inc(ret) >< (int i) => ret~(i+1); // a rule for inc >< (int i) @@ -119,7 +170,7 @@ $ make thread ``` $ ./inpla -f sample/gcd.in - Inpla 0.4.1 : Interaction nets as a programming language [built: 21 Sept. 2021] + Inpla 0.5.0 : Interaction nets as a programming language [built: 28 Oct. 2021] (4 interactions, 0.00 sec) 7 @@ -152,7 +203,7 @@ $ make thread ``` $ ./inpla -f sample/isort.in - Inpla 0.4.1 : Interaction nets as a programming language [built: 21 Sept. 2021] + Inpla 0.5.0 : Interaction nets as a programming language [built: 28 Oct. 2021] (16 interactions, 0.00 sec) [1,2,3,6,9] @@ -188,7 +239,7 @@ $ make thread ``` $ ./inpla -f sample/qsort.in - Inpla 0.4.1 : Interaction nets as a programming language [built: 21 Sept. 2021] + Inpla 0.5.0 : Interaction nets as a programming language [built: 28 Oct. 2021] (22 interactions, 0.00 sec) [1,2,3,6,9] @@ -624,19 +675,21 @@ If the `add(r, b)~3` is operated first, it causes core dump error because the `b ### Built-in rules of attributes in the anonymous agents -There is a built-in rule for attributes on the two anonymous agents. This could be required to calculate attributes obtained as evaluation results of two nets. In this version, we have the following rules as built-in: +There are built-in rules for arithmetic operations between two agents by using `Add`, `Sub`, `Mul`, `Div`, `Mod` agents as addition, subtraction, multiplication, division and modulo, respectively. Rules for the `Add` are defined as follows, and the others are also defined the same way: ``` -Add(result, y)><(int x) => Addn(result, x)~y; -Addn(result, int x)><(int y) => result~(x+y); +Add(result, y)><(int x) => _Add(result, x)~y; +_Add(result, int x)><(int y) => result~(x+y); ``` - Example: ``` ->>> Add(r, 3)~5; // Add is already defined as a bulit-in +>>> Add(r,3)~5; // Add is already defined as a bulit-in >>> r; 8 +>>> result << Sub(r,2) // This is also written as an abbreviation form. +6 >>> ``` @@ -661,10 +714,10 @@ The sequence of `<condition-on-attributes> ` must be finished with the otherwise - Example: The following shows rules to obtain a list that contains only even numbers: ``` -// Rules (because it is long definition, so copy and paste is recommended) +// Rules evenList(result) >< [] => r~[]; evenList(result) >< (int x):xs -| x%2==0 => result~(x:r1), evenList(r1)~xs +| x%2==0 => result~(x:cnt), evenList(cnt)~xs | _ => evenList(result)~xs; ``` @@ -681,11 +734,15 @@ evenList(result) >< (int x):xs fib(result) >< (int n) | n == 0 => result~0 | n == 1 => result~1 -| _ => fib(r1)~(n-1), fib(r2)~(n-1), Add(result, r2)~r1; +| _ => fib(r1)~(n-1), fib(r2)~(n-2), Add(result, r2)~r1; // * We cannot write result~(r1+r2) -// because r1 and r2 are not recognised as attributes. -// Therefore, we have to apply those to the built-in rule Add(r, int x)><(int y). +// because r1, r2 may be not connected to attributes in the anonymous agents, +// thus we have to leave the addition until fib(r1) and fib(r2) are finished. +// For this purpose we must use addition operation between agents as +// Add(result, r2)~r1. +// In this case, after r1,r2 are connected to (int y), (int x), +// y+x is executed and the addition result is connected to the result. ``` ``` @@ -702,7 +759,7 @@ fib(result) >< (int n) - Inpla has the following commands: - `free` *name1* ... *name_n* `;` - The *name1* ... *name_n* and connected terms from these are disposed. To dispose every living name and term connected from those, type `free ifce;`, where the `ifce` is an abbreviation of *interface* that is called for the set of living names. + The *name1* ... *name_n* and connected terms from these are disposed. To dispose every living name and term connected from those, type `free ifce;`, where the `ifce` is an abbreviation of *interface* that is called for the set of names that live and occur once. - *name1* ... *name_n* `;` Put terms connected from the *name1* ... *name_n*. To put every term connected from the interface, type `ifce;`. - `prnat` *name*`;` @@ -718,7 +775,16 @@ fib(result) >< (int n) -## Extensions in Version 0.4 +## Feature of Version 0.4 + +#### Summaries +- Integer numbers can be written the same as one of the first-class objects. +- Interaction rules can re-allocate heaps of the rule agents to agents in nets. This re-allocation is specified by modifications such as `(*L)`, `(*R)`, called reuse annotation [1], in front of agents in nets, such as `(*L)Add(r,a)`. This re-allocation can improve performance in multi-threaded execution. This is experimental, thus in future version these can be decided automatically, so please do not care so much. +- Weak reduction strategy is supported. It turns on by invoked with ```-w``` option, and then only connections that have living names are evaluated. +- Nested guards in conditional rules are supporeted. +- Line edit supports multi-line inputs. + + ### Reuse annotations @@ -736,7 +802,7 @@ In interaction rule definitions, we can specify which agent is reused in the net ### Weak reduction strategy -In this reduction strategy, only connections that have living names are evaluated. This is taken for non-terminate computation such as fixed point combinator and process networks. +In this reduction strategy, only connections that have interface names (thus, live and occur once) are evaluated. This is taken for non-terminate computation such as fixed point combinator and process networks. - Example: We have a sample net in `sample/processnet1.in` that keep producing natural numbers from 1 and output these to the port `r`: @@ -765,7 +831,7 @@ In this reduction strategy, only connections that have living names are evaluate ``` $ ./inpla -w - Inpla 0.4.1 : Interaction nets as a programming language [built: 21 Sept. 2021] + Inpla 0.5.0 (Weak Strategy) : Interaction nets as a programming language [28 Oct. 2021] >>> use "sample/processnet1.in"; (2 interactions, 0.00 sec) >>> ifce; diff --git a/pic/merger.png b/pic/merger.png Binary files differnew file mode 100644 index 0000000..54adfaf --- /dev/null +++ b/pic/merger.png diff --git a/sample/245II_abbr.in b/sample/245II_abbr.in new file mode 100644 index 0000000..a6797d8 --- /dev/null +++ b/sample/245II_abbr.in @@ -0,0 +1,98 @@ +// 245II in YALE encoding + +// Rules + +D >< V => ; +B(a,b,c) >< Z => a~c, b~Z; +B(a,b,c) >< Lam(x,t,v) => b~Lam(x,t,w), v~DB(a,w,c); +DB(a,b,c) >< V => a~c, b~V; +C(x,y) >< Z => x~Z, y~Z; +C(x,y) >< Lam(s,t,u) => + x~Lam(a,b,c), y~Lam(d,e,f), + s~Delta(a,d), t~Delta(b,e), u~C(c,f); +C(x,y) >< V => x~V, y~V; +Delta(x,y) >< Delta(a,b) => x~a, y~b; +B(x,a,b) >< Delta(c,d) => x~CB(a,b,Delta(c,d)); +Delta(a,b) >< CB(x,y,z) => + x~Delta(c,d), y~Delta(e,f), z~Delta(B(a,c,e),B(b,d,f)); +Delta(x,y) >< S(z) => + x~S(a), y~S(b), z~Delta(a,b); +Delta(x,y) >< Z => x~Z, y~Z; +Delta(x,y) >< V => x~V, y~V; +Delta(x,y) >< C(t,s) => + x~C(a,b), y~C(c,d), t~Delta(b,d), s~Delta(a,c); +Delta(x,y) >< AppTo(t,s) => + x~AppTo(a,b), y~AppTo(c,d), t~Delta(a,c), s~Delta(b,d); +Delta(x,y) >< Lam(t,s,u)=> + x~Lam(a,b,c), y~Lam(d,e,f), + t~Delta(a,d), s~Delta(b,e), u~Delta(c,f); +DB(x,y,z) >< CB(t,s,u) => + x~CB(d,e,u), y~CB(t,f,d), s~DB(e,f,z); +C(x,y) >< CB(t,s,u) => + x~CB(a,b,c), y~CB(d,e,f), + t~Delta(a,d), s~C(b,e), u~C(c,f); +D >< CB(a,b,c) => a~c, b~D; + +Eps >< Eps => ; +Eps >< S(x) => x~Eps; +Eps >< V => ; +Eps >< D =>; +Eps >< Delta(t,s) => t~Eps,s~Eps; +Eps >< Lam(t,s,u) => t~Eps,s~Eps,u~Eps; +Eps >< AppTo(t,s) => t~Eps,s~Eps; +Eps >< B(t,s,u) => t~Eps,s~Eps,u~Eps; +Eps >< CB(t,s,u) => t~Eps,s~Eps,u~Eps; + + + +Lam(x,t,c) >< AppTo(result,s) => result~t, x~s, c~D; +// We can write this avtive pair in nets as +// result << AppTo(s, lam_term) for AppTo(result, s)~ lam_term. + +// If the `<<' is defined as user macro, then it becomes more readable: +// result << App(lam_term, s) =def= lam_term ~ App(result, s) + + +// Nets +id1 ~ Lam(x,x,V); +id2 ~ Lam(x,x,V); + + +// lam f. lam x. f(fx) +two ~ Lam(fb, Lam(x,r2,c),V), + fb ~ B(c,f,V), + f2,f1 << C(f), // C(f2,f1) ~ f + r2 << AppTo(r1, f2), + r1 << AppTo(x, f1); + + +// lam f. lam x. f(f(f(fx))) +four ~ Lam(fb, Lam(x, r4, c), V), + fb~B(c, f, V), + f4, C(f3, C(f2, f1)) << C(f), + r4 << AppTo(r3, f4), + r3 << AppTo(r2, f3), + r2 << AppTo(r1, f2), + r1 << AppTo(x, f1); + + +// lam f. lam x. f(f(f(f(fx)))) +five ~ Lam(fb, Lam(x, r5, c), V), + fb~B(c, f, V), + f5, C(f4, C(f3, C(f2, f1))) << C(f), + r5 << AppTo(r4, f5), + r4 << AppTo(r3, f4), + r3 << AppTo(r2, f3), + r2 << AppTo(r1, f2), + r1 << AppTo(x, f1); + + + +// (((24)5)I)I +aux24 << AppTo(four, two); +aux245 << AppTo(five, aux24); +aux245I << AppTo(id1, aux245); +aux245II << AppTo(id2, aux245I); + +aux245II; +exit; diff --git a/sample/fib_9.in b/sample/fib_9.in index f4f17e8..7c4af1f 100644 --- a/sample/fib_9.in +++ b/sample/fib_9.in @@ -8,7 +8,7 @@ fib(ret) >< (int n) // Note: Add is implemented as a built-in agent such that: -// Add(ret, int m) ~ (int n) --> ret~(n+m); +// Add(ret, int m) ~ (int n) --> ret~(m+n); // Nets fib(ret)~9; diff --git a/sample/fib_9_abbr.in b/sample/fib_9_abbr.in new file mode 100644 index 0000000..57a8c62 --- /dev/null +++ b/sample/fib_9_abbr.in @@ -0,0 +1,16 @@ +// Fibonacci number + +// Rules +fib(ret) >< (int n) +| n == 0 => ret~0 +| n == 1 => ret~1 +| _ => cnt1 << fib(n-1), cnt2 << fib(n-2), ret << Add(cnt1,cnt2); + + +// Note: Add is implemented as a built-in agent such that: +// Add(ret, int m) ~ (int n) --> ret~(m+n); + +// Nets +ret << fib(9); +ret; + diff --git a/sample/linear-systemT.in b/sample/linear-systemT.in index 648d9e1..f0e3ccb 100644 --- a/sample/linear-systemT.in +++ b/sample/linear-systemT.in @@ -36,7 +36,7 @@ Dup(x,y) >< Itc(a,b,c,d) => a~Dup(u1,u2), b~Dup(w1,w2), c~Dup(z1,z2), d~Dup(k1,k2); -/* needed */ +/* required */ Dup(x,y) >< B(a,b,c) => x~B(u1,z1,w1), y~B(u2,z2,w2), a~Dup(u1,u2), b~Dup(z1,z2), c~Dup(w1,w2); Dup(x,y) >< Lam(a,b,c) => x~Lam(w1,u1,z1), y~Lam(w2,u2,z2), @@ -116,7 +116,7 @@ free res; // Ack 3 10 -// ver 1: the same as the example on the paper +// ver.1: the same as the example on the paper a~S(S(S(Z))), b~S(S(S(S(S(S(S(S(S(S(Z)))))))))); Iter(t,x,Lamc(x1,S(x1)))~Lamc(B(V,Iter(r2,S(y),S(Z)),Lam(y,r2,r1)),r1), @@ -124,7 +124,7 @@ Lamc(x,t)~App(a,App(b, r)); prnat r; free r; -// ver 2: \m.(\n.(iter m (\x.(S x)) (\x.(\y.(iter (S y) (S 0) x))) n)) +// ver.2: \m.(\n.(iter m (\x.(S x)) (\x.(\y.(iter (S y) (S 0) x))) n)) a~S(S(S(Z))), b~S(S(S(S(S(S(S(S(S(S(Z)))))))))); Iter(App(n,apr),x,Lamc(x1,S(x1)))~Lamc(B(V,Iter(r2,S(y),S(Z)),Lam(y,r2,r1)),r1), @@ -132,7 +132,7 @@ Lamc(B(V,x,Lam(n,apr,nr)),nr)~App(a,App(b, r)); prnat r; free r; -// ver 3: another encoding of ver 2. +// ver.3: another encoding of ver.2. a~S(S(S(Z))), b~S(S(S(S(S(S(S(S(S(S(Z)))))))))); Iter(t,m,Lamc(x1,S(x1)))~Lamc(B(V,Iter(r2,S(y),S(Z)),Lam(y,r2,r1)),r1), diff --git a/sample/processnet1.in b/sample/processnet1.in index d02404e..c648650 100644 --- a/sample/processnet1.in +++ b/sample/processnet1.in @@ -9,6 +9,8 @@ inc(r) >< [] => r~[]; // Nets dup(r,w)~r1, inc(r1) ~ (0:w); +// r,w << dup(r1), r1 << inc(0:w) + // +-----+ +-----+ +---+ // r ----| | r1 | | | | // | dup |--->---| inc |---><---| 0 |----+ diff --git a/sample/processnet_fib.in b/sample/processnet_fib.in new file mode 100644 index 0000000..ab19eec --- /dev/null +++ b/sample/processnet_fib.in @@ -0,0 +1,30 @@ +// Rules +dup(a1,a2) >< (int i):xs => a1~(i:xs1), a2~(i:xs2), dup(xs1,xs2)~xs; +dup(a1,a2) >< [] => a1~[], a2~[]; + +add(r, ys) >< (int i):xs => addn(r, xs, i)~ys; +addn(r, xs, int i) >< (int j):ys => r~(i+j):w, add(w,ys)~xs; + + +// Nets +dup(r, r1)~(1:xs), r1~add(sum, w), dup(xs, w)~(1:sum); + +// r,r1 << dup(1:xs), +// xs,w << dup(1:sum), +// sum << add(r1,w); + +// +-----+ +---+ +// r ----| | | | xs +-----+ +---+ +// | dup |---><---| 1 |-----| | | | +// +---| | | | | dup |---><---| 1 |----+ +// | +-----+ +---+ +--| | | | | +// | | +-----+ +---+ | sum +// | | | +// | | +-----+ +// | | | add | +// | | +-----+ +// | | w | | +// | +------------------------+ v +// | r1 | +// +------------------------------------------------------+ +// @@ -36,7 +36,7 @@ char *recordSymbol(SymbolTable *table, char *name) { // The `name' has existed already, // and table->sym[i] is used instead of that, // so starduped memory for the `name' should be freed here. - free(name); + // free(name); return table->sym[i]; } @@ -150,6 +150,7 @@ void ast_recordConst(char *name, int val) { } + Ast *ast_makeAST(AST_ID id, Ast *left, Ast *right) { Ast *ptr; if ((id == AST_AGENT) && (right == NULL)) { @@ -252,7 +253,7 @@ void puts_ast(Ast *p) { "(*L)", "(*R)", // extension - "TUPLE", + "TUPLE", "PPAIR", "INT", "LD", "ADD", "SUB", "MUL", "DIV", "MOD", "LT", "LE", "EQ", "NE", "UNM", "CONS", "NIL", "OPCONS", @@ -276,6 +277,11 @@ void puts_ast(Ast *p) { puts_ast(p->right); printf(")"); break; + case AST_PPAIR: + printf("PPAIR("); + puts_ast(p->right); + printf(")"); + break; case AST_NIL: printf("NIL"); break; @@ -295,6 +301,88 @@ void puts_ast(Ast *p) { } +Ast *ast_unfoldABR(Ast *left, char *sym, Ast *paramlist) { + // input: + // left << (AST_AGENT, sym, paramlist) + + // output: + // p1,p2,...,pn << (AST_AGENT, sym, params @ [param]) + // ==> (AST_CNCT left right) + // where left = (AST_AGENT sym, p1,p2,...,pn,params) + // right = (AST_NAME param) + + if (!strcmp(sym, "Append")) { + // paramlist: [a,b] => [b,a] + if (paramlist->right != NULL) { + Ast *tmp = paramlist->left; // tmp for a + paramlist->left = paramlist->right->left; // a := b + paramlist->right->left = tmp; // b := a + } + } else if (!strcmp(sym, "Merger")) { + // left << Merger(paramlist) ==> Merger(left) ~ (paramlist) + Ast *agent_left = ast_makeAST(AST_AGENT, ast_makeSymbol("Merger"), left); + Ast *agent_right = ast_makeTuple(paramlist); + Ast *cnct = ast_makeAST(AST_CNCT, agent_left, agent_right); + return cnct; + } + + //puts_ast(left);puts(""); + //puts_ast(paramlist);puts(""); + + Ast *params, *param, *at; + + // paramlist: (AST_LIST elem next) + if (paramlist->right == NULL) { + // [x] => [], x + param = paramlist->left; + params = NULL; + } else { + params = param = NULL; + + // params@[param] => params, param + at = paramlist; + while (at->right != NULL) { + if (at->right->right == NULL) { + param = at->right->left; // compoment + at->right = NULL; // break the list chain + params = paramlist; // params is the list whose last is just broken + break; + } + at = at->right; + } + } + + // puts_ast(params);puts(""); + // puts_ast(param);puts(""); + + + // make left as left@params + at = left; + while (at != NULL) { + if (at->right == NULL) { + at->right = params; + break; + } + at = at->right; + } + // puts_ast(left);puts(""); + + + Ast *agent_left = ast_makeAST(AST_AGENT, ast_makeSymbol(sym), left); + Ast *agent_right = param; + Ast *cnct = ast_makeAST(AST_CNCT, agent_left, agent_right); + + //puts_ast(agent_left);puts(""); + //puts_ast(agent_right);puts(""); + + //exit(1); + return cnct; + +} + + + + Ast *ast_remove_tuple1(Ast *p) { if (p==NULL) return p; @@ -13,8 +13,8 @@ typedef enum { // annotation AST_ANNOTATION_L, AST_ANNOTATION_R, - // builtin tuble - AST_TUPLE, + // builtin tuple + AST_TUPLE, AST_PPAIR, // operation AST_INT, AST_LD, AST_PLUS, AST_SUB, AST_MUL, AST_DIV, AST_MOD, @@ -50,7 +50,7 @@ void puts_ast(Ast *p); Ast *ast_paramToCons(Ast *ast); void ast_recordConst(char *name, int val); Ast *ast_remove_tuple1(Ast *p); - +Ast *ast_unfoldABR(Ast *left, char *sym, Ast *paramlist); #define ast_makeCons(x1,x2) ast_makeAST(AST_LIST,x1,x2) #define ast_makeList1(x1) ast_makeAST(AST_LIST,x1,NULL) diff --git a/src/id_table.c b/src/id_table.c index b7b267b..cbcee78 100644 --- a/src/id_table.c +++ b/src/id_table.c @@ -35,10 +35,19 @@ void IdTable_init() { IdTable[ID_CONS].arity = 2; IdTable[ID_INTAGENT].arity = 1; + IdTable[ID_APPEND].arity = 2; + IdTable[ID_MERGER].arity = 1; + IdTable[ID_MERGER_P].arity = 1; IdTable[ID_ADD].arity = 2; IdTable[ID_ADD2].arity = 2; - // IdTable[ID_APPEND].arity = 2; - // IdTable[ID_APPEND2].arity = 2; + IdTable[ID_SUB].arity = 2; + IdTable[ID_SUB2].arity = 2; + IdTable[ID_MUL].arity = 2; + IdTable[ID_MUL2].arity = 2; + IdTable[ID_DIV].arity = 2; + IdTable[ID_DIV2].arity = 2; + IdTable[ID_MOD].arity = 2; + IdTable[ID_MOD2].arity = 2; IdTable[ID_INT].name = "int"; IdTable[ID_TUPLE0].name = "Tuple0"; @@ -51,10 +60,19 @@ void IdTable_init() { IdTable[ID_CONS].name = "Cons"; IdTable[ID_INTAGENT].name = "Int"; - IdTable[ID_ADD].name = "Add"; - IdTable[ID_ADD2].name = "Add2"; IdTable[ID_APPEND].name = "Append"; - IdTable[ID_APPEND2].name = "Append2"; + IdTable[ID_MERGER].name = "Merger"; + IdTable[ID_MERGER_P].name = "_MergerP"; + IdTable[ID_ADD].name = "Add"; + IdTable[ID_ADD2].name = "_Add"; + IdTable[ID_SUB].name = "Sub"; + IdTable[ID_SUB2].name = "_Sub"; + IdTable[ID_MUL].name = "Mul"; + IdTable[ID_MUL2].name = "_Mul"; + IdTable[ID_DIV].name = "Div"; + IdTable[ID_DIV2].name = "_Div"; + IdTable[ID_MOD].name = "Mod"; + IdTable[ID_MOD2].name = "_Mod"; } @@ -67,16 +85,22 @@ int IdTable_getid_builtin_funcAgent(Ast *agent) { return -1; } - if (strcmp((char *)agent->left->sym, "Add2") == 0) { - id = ID_ADD2; - } else if (strcmp((char *)agent->left->sym, "Add") == 0) { + if (strcmp((char *)agent->left->sym, "Add") == 0) { id = ID_ADD; + } else if (strcmp((char *)agent->left->sym, "Sub") == 0) { + id = ID_SUB; + } else if (strcmp((char *)agent->left->sym, "Mul") == 0) { + id = ID_MUL; + } else if (strcmp((char *)agent->left->sym, "Div") == 0) { + id = ID_DIV; + } else if (strcmp((char *)agent->left->sym, "Mod") == 0) { + id = ID_MOD; } else if (strcmp((char *)agent->left->sym, "Append") == 0) { id = ID_APPEND; - } else if (strcmp((char *)agent->left->sym, "Append2") == 0) { - id = ID_APPEND2; } else if (strcmp((char *)agent->left->sym, "Int") == 0) { id = ID_INTAGENT; + } else if (strcmp((char *)agent->left->sym, "Merger") == 0) { + id = ID_MERGER; } return id; @@ -100,7 +124,8 @@ int IdTable_is_builtin_rule(Ast *agentL, Ast *agentR) { int idL = IdTable_getid_builtin_funcAgent(agentL); if (agentR->id == AST_INT) { - if ((idL == ID_ADD) || (idL == ID_ADD2)) { + if ((idL == ID_ADD) || (idL == ID_SUB) || (idL == ID_MUL) + || (idL == ID_DIV) || (idL == ID_MOD)) { return 1; } return 0; @@ -112,6 +137,16 @@ int IdTable_is_builtin_rule(Ast *agentL, Ast *agentR) { } return 0; } + + if (idL == ID_MERGER) { + if ((agentR->id == AST_TUPLE) && (agentR->intval == 2)) { + // Merger >< Tuple2 + return 1; + } + return 0; + } + + return 0; } @@ -133,7 +168,7 @@ void IdTable_set_arity(int id, int arity) if ((IdTable[id].arity == -1) || (IdTable[id].arity == arity)) { IdTable[id].arity = arity; } else { - printf("Warning: The agent '%s' has been already defined as whose arity is %d, but now redefined as the arity is %d.\n", + printf("Warning: The agent '%s' has been already defined as whose arity is %d, but now used as the arity is %d.\n", IdTable[id].name, IdTable[id].arity, arity); IdTable[id].arity = arity; } @@ -162,10 +197,12 @@ int IdTable_new_agentid() { int IdTable_new_gnameid() { NextGnameId++; - if (NextAgentId > IDTABLE_SIZE) { - printf("ERROR: The number of agents exceeded the size of names in SYMTABLE (%d)\n", - ID_NAME); + if (NextGnameId < IDTABLE_SIZE) { + return(NextGnameId); + } else { + + printf("ERROR: The total number of agents and names exceeded the size of names in IDTABLE (%d)\n", + IDTABLE_SIZE); exit(-1); } - return(NextGnameId); } diff --git a/src/id_table.h b/src/id_table.h index 8dbdeef..7567b70 100644 --- a/src/id_table.h +++ b/src/id_table.h @@ -26,17 +26,28 @@ #define ID_CONS 8 #define IS_LISTID(id) ((id == ID_NIL) && (id == ID_CONS)) -#define ID_INTAGENT 9 - -#define START_ID_OF_BUILTIN_AGENT 10 -#define ID_ADD 10 -#define ID_ADD2 11 -#define ID_APPEND 12 -#define ID_APPEND2 13 -#define END_ID_OF_BUILTIN_AGENT 13 +#define ID_INTAGENT 10 // This is an experimental dummy agent + // to show the use effect of Int agent. + + +#define START_ID_OF_BUILTIN_AGENT 15 +#define ID_APPEND 15 +#define ID_MERGER 16 +#define ID_MERGER_P 17 +#define ID_ADD 18 +#define ID_ADD2 19 +#define ID_SUB 20 +#define ID_SUB2 21 +#define ID_MUL 22 +#define ID_MUL2 23 +#define ID_DIV 24 +#define ID_DIV2 25 +#define ID_MOD 26 +#define ID_MOD2 27 +#define END_ID_OF_BUILTIN_AGENT 27 -#define START_ID_OF_AGENT 20 +#define START_ID_OF_AGENT END_ID_OF_BUILTIN_AGENT+1 //#define NUM_AGENTS 1024 #define END_ID_OF_AGENT 255 #define NUM_AGENTS END_ID_OF_AGENT+1 // 256 diff --git a/src/inpla.l b/src/inpla.l index f5b386d..85bf522 100644 --- a/src/inpla.l +++ b/src/inpla.l @@ -6,7 +6,6 @@ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result = mygetinput(buf, max_size); -// lineno de kubetu? static int mygetinput(char *buf, int size) { char *line; if (feof(yyin)) return YY_NULL; @@ -23,6 +22,7 @@ static int mygetinput(char *buf, int size) { return len; } + linenoiseSetMultiLine(1); if (yylineno == 1) { line = linenoise(">>> "); } else { @@ -30,8 +30,10 @@ static int mygetinput(char *buf, int size) { } if(!line) return YY_NULL; if(strlen(line) > size-2){ - fprintf(stderr,"input line too long\n"); return YY_NULL; } - sprintf(buf,"%s\n",line); + fprintf(stderr,"input line too long\n"); + return YY_NULL; + } + sprintf(buf, "%s\n", line); linenoiseHistoryAdd(line); linenoiseHistorySave(".inpla.history.txt"); free(line); @@ -101,7 +103,7 @@ char *Parse_closeStringBuffer() { <INITIAL>"/" return (DIV); <INITIAL>"%" return (MOD); <INITIAL>"_" return (ANY); -<INITIAL>"?" return (QUE); +<INITIAL>"<<" return (ABR); <INITIAL>"int" return(INT); @@ -132,7 +134,7 @@ char *Parse_closeStringBuffer() { <INITIAL>"*R" return(ANNOTATE_R); <INITIAL>[a-z][a-zA-Z0-9_'\.]* { yylval.chval = strdup(yytext); return (NAME);} -<INITIAL>[_A-Z][a-zA-Z0-9_'\.]* { yylval.chval = strdup(yytext); +<INITIAL>[A-Z][a-zA-Z0-9_'\.]* { yylval.chval = strdup(yytext); return (AGENT);} <INITIAL>[0-9]+ { yylval.intval = atoi(yytext); return (INT_LITERAL);} @@ -143,8 +145,8 @@ char *Parse_closeStringBuffer() { <COM_STATE>\n ; <COM_STATE>"*/" BEGIN INITIAL; //comment -<INITIAL>\r\n {} -<INITIAL>[\n|\r] {} +<INITIAL>\r\n ; +<INITIAL>[\n|\r] ; <INITIAL>[ \t]+ ; <INITIAL><<EOF>> {return END_OF_FILE;} <INITIAL>\" { diff --git a/src/inpla.y b/src/inpla.y index ff65f39..1545b81 100644 --- a/src/inpla.y +++ b/src/inpla.y @@ -6,9 +6,9 @@ #include <unistd.h> #include <errno.h> #include <sched.h> - -#include "linenoise/linenoise.h" +#include "linenoise/linenoise.h" + #include "ast.h" #include "id_table.h" #include "name_table.h" @@ -48,8 +48,8 @@ int ActiveThreadNum=0; //#define YYDEBUG 1 -#define VERSION "0.4.2" -#define BUILT_DATE "16 Oct. 2021" +#define VERSION "0.5.0" +#define BUILT_DATE "28 Oct. 2021" extern FILE *yyin; @@ -186,7 +186,7 @@ void eat_to_newline(void) %token <chval> NAME AGENT %token <intval> INT_LITERAL %token <chval> STRING_LITERAL -%token LP RP LC RC LB RB COMMA CROSS DELIMITER QUE +%token LP RP LC RC LB RB COMMA CROSS DELIMITER ABR %token COLON %token TO CNCT @@ -441,7 +441,7 @@ val_declare agent_cons : LB astterm PIPE astterm RB -{$$ = ast_makeAST(AST_OPCONS, NULL, ast_makeList2($2, $4)); } +{ $$ = ast_makeAST(AST_OPCONS, NULL, ast_makeList2($2, $4)); } ; agent_list @@ -464,8 +464,8 @@ agentterm ; -astparam : -LP RP { $$ = NULL; } +astparam +: LP RP { $$ = NULL; } | LP astparams RP { $$ = $2; } ; @@ -476,8 +476,16 @@ astparams ap : astterm CNCT astterm { $$ = ast_makeAST(AST_CNCT, $1, $3); } +// +| astparams ABR AGENT LP astparams RP +{ $$ = ast_unfoldABR($1, $3, $5); } +// +| astparams ABR NAME LP astparams RP +{ $$ = ast_unfoldABR($1, $3, $5); } ; + + aplist : ap { $$ = ast_makeList1($1); } | aplist COMMA ap { $$ = ast_addLast($1, $3); } @@ -747,7 +755,7 @@ VALUE myallocAgent(Heap *hp) { } -static inline +//static inline VALUE myallocName(Heap *hp) { #ifdef MALLOC @@ -1033,7 +1041,8 @@ char *Pretty_Name(VALUE a) { #endif -#define PUTS_ELEMENTS_NUM 12 +//#define PUTS_ELEMENTS_NUM 12 +#define PUTS_ELEMENTS_NUM 30 static int Puts_list_element=0; @@ -1044,7 +1053,7 @@ void puts_term(VALUE ptr) { printf("%d", FIX2INT(ptr)); return; } else if (BASIC(ptr) == NULL) { - printf("[NULL]"); + printf("<NULL>"); return; } @@ -1124,7 +1133,7 @@ void puts_term(VALUE ptr) { } } - + } else { // Agent int i, arity; @@ -1230,7 +1239,8 @@ void free_names_ast(Ast *ast) { while (param != NULL) { char *sym = param->left->sym; - flush_name_port0(NameTable_get_heap(sym)); + VALUE heap = NameTable_get_heap(sym); + flush_name_port0(heap); param = ast_getTail(param); } } @@ -2663,6 +2673,7 @@ int CompileTermFromAst(Ast *ptr, int target) { return result; break; + case AST_CONS: if (target == -1) { result = CmEnv_newreg(); @@ -2730,7 +2741,7 @@ int CompileTermFromAst(Ast *ptr, int target) { break; */ - + case AST_TUPLE: arity = ptr->intval; @@ -3765,10 +3776,15 @@ void makeRule(Ast *ast) { // 単純に ruleAgentL、ruleAgentR を入れ替えれば良いわけではない。 if (idL > idR) { - // 標準では Append(xs, r) >< [y|ys] なので + // Generally the order should be as Append(xs,r) >< y:ys, + // so idL should be greater than idR. + + // JAPANESE: 標準では Append(xs, r) >< [y|ys] なので // idL の方が大きくなって欲しい - // annotation が (*L) なら左側、(*R) なら右側を指すものとする + + // (*L) is interpreted as the left-hand side agent, (*R) is the right one. + // JAPANESE: annotation が (*L) なら左側、(*R) なら右側を指すものとする setAnnotateLR(VM_OFFSET_ANNOTATE_L, VM_OFFSET_ANNOTATE_R); } else { @@ -3781,8 +3797,11 @@ void makeRule(Ast *ast) { idTmp = idL; idL = idR; idR = idTmp; - - // aplist 内の (*L) (*R) はそのままにしておき、 + + // Keep the occurrence (*L) and (*R) in aplist, + // change the interpretation of (*L) as (*R), vice versa. + + // JAPANESE: aplist 内の (*L) (*R) はそのままにしておき、 // annotation が (*L) なら右側、(*R) なら左側を指すものとする setAnnotateLR(VM_OFFSET_ANNOTATE_R, VM_OFFSET_ANNOTATE_L); } @@ -3790,7 +3809,8 @@ void makeRule(Ast *ast) { { int arity; - // code の先頭2つは idL、idR の arity を格納する + // IMPORTANT: + // The first two codes store arities of idL and idR. if (idL == ID_INT) { arity = 0; } else { @@ -3816,14 +3836,14 @@ void makeRule(Ast *ast) { if (idL == ID_INT) { setMetaL_asIntName(ruleL); - CmEnv.annotateL = ANNOTATE_AS_INT_AGENT; // FreeL 出力を防ぐ + CmEnv.annotateL = ANNOTATE_AS_INT_AGENT; // to prevent putting FreeL out } else { setMetaL(ruleL); } if (idR == ID_INT) { setMetaR_asIntName(ruleR); - CmEnv.annotateR = ANNOTATE_AS_INT_AGENT; // FreeR 出力を防ぐ + CmEnv.annotateR = ANNOTATE_AS_INT_AGENT; // to prevent putting FreeR out } else { setMetaR(ruleR); } @@ -3833,7 +3853,6 @@ void makeRule(Ast *ast) { - //code_size = CompileGuardBodiesFromAST(guard_bodies, code, code_size); code_size += CompileIfSentenceFromAST(if_sentence, code, code_size); if (code_size < 0) return; @@ -6317,12 +6336,14 @@ loop_a2IsFixnum: getRuleCodeInt(a1, &code); - if (code == NULL) { - + if (code == NULL) { // built-in switch (BASIC(a1)->id) { case ID_ADD: { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif BASIC(a1)->id = ID_ADD2; VALUE a1port1 = AGENT(a1)->port[1]; AGENT(a1)->port[1] = a2; @@ -6331,14 +6352,118 @@ loop_a2IsFixnum: } case ID_ADD2: { - int m = FIX2INT(AGENT(a1)->port[1]); - int n = FIX2INT(a2); +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + // r << Add(m,n) + int n = FIX2INT(AGENT(a1)->port[1]); + int m = FIX2INT(a2); a2 = INT2FIX(m+n); VALUE a1port0 = AGENT(a1)->port[0]; freeAgent(a1); a1 = a1port0; goto loop; } + case ID_SUB: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + BASIC(a1)->id = ID_SUB2; + VALUE a1port1 = AGENT(a1)->port[1]; + AGENT(a1)->port[1] = a2; + a2 = a1port1; + goto loop; + } + case ID_SUB2: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + // r << Sub(m,n) + int n = FIX2INT(AGENT(a1)->port[1]); + int m = FIX2INT(a2); + a2 = INT2FIX(m-n); + VALUE a1port0 = AGENT(a1)->port[0]; + freeAgent(a1); + a1 = a1port0; + goto loop; + } + case ID_MUL: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + BASIC(a1)->id = ID_MUL2; + VALUE a1port1 = AGENT(a1)->port[1]; + AGENT(a1)->port[1] = a2; + a2 = a1port1; + goto loop; + } + case ID_MUL2: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + // r << Mult(m,n) + int n = FIX2INT(AGENT(a1)->port[1]); + int m = FIX2INT(a2); + a2 = INT2FIX(m*n); + VALUE a1port0 = AGENT(a1)->port[0]; + freeAgent(a1); + a1 = a1port0; + goto loop; + } + case ID_DIV: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + BASIC(a1)->id = ID_DIV2; + VALUE a1port1 = AGENT(a1)->port[1]; + AGENT(a1)->port[1] = a2; + a2 = a1port1; + goto loop; + } + case ID_DIV2: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + // r << DIV(m,n) + int n = FIX2INT(AGENT(a1)->port[1]); + int m = FIX2INT(a2); + a2 = INT2FIX(m/n); + VALUE a1port0 = AGENT(a1)->port[0]; + freeAgent(a1); + a1 = a1port0; + goto loop; + } + case ID_MOD: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + BASIC(a1)->id = ID_MOD2; + VALUE a1port1 = AGENT(a1)->port[1]; + AGENT(a1)->port[1] = a2; + a2 = a1port1; + goto loop; + } + case ID_MOD2: + { +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + // r << MOD(m,n) + int n = FIX2INT(AGENT(a1)->port[1]); + int m = FIX2INT(a2); + a2 = INT2FIX(m%n); + VALUE a1port0 = AGENT(a1)->port[0]; + freeAgent(a1); + a1 = a1port0; + goto loop; + } } @@ -6435,98 +6560,10 @@ loop_a2IsAgent: // a1 が fixnum if (IS_FIXNUM(a1)) { // fixnum >< agent - - void **code = NULL; - - getRuleCodeInt(a2, &code); - - if (code == NULL) { - - - // built-in - VALUE tmp = a1; - a1 = a2; - a2 = tmp; - switch (BASIC(a1)->id) { - - case ID_ADD: - { - BASIC(a1)->id = ID_ADD2; - VALUE a1port1 = AGENT(a1)->port[1]; - AGENT(a1)->port[1] = a2; - a2 = a1port1; - goto loop; - } - case ID_ADD2: - { - int m = FIX2INT(AGENT(a1)->port[1]); - int n = FIX2INT(a2); - a2 = INT2FIX(m+n); - VALUE a1port0 = AGENT(a1)->port[0]; - freeAgent(a1); - a1 = a1port0; - goto loop; - } - - } - - - - - printf("Runtime Error: There is no interaction rule for the following pair:\n "); - puts_term(a1); - printf("~"); - puts_term(a2); - puts(""); - - if (yyin != stdin) exit(-1); - -#ifndef THREAD - mark_and_sweep(); - return; -#else - printf("Retrieve is not supported in the multi-threaded version.\n"); - exit(-1); -#endif - } - - int i; - unsigned long arity; - arity = (unsigned long)code[0]; - - switch(arity) { - case 0: - break; - - case 1: - vm->agentReg[VM_OFFSET_META_R(0)] = AGENT(a2)->port[0]; - break; - - case 2: - vm->agentReg[VM_OFFSET_META_R(0)] = AGENT(a2)->port[0]; - vm->agentReg[VM_OFFSET_META_R(1)] = AGENT(a2)->port[1]; - break; - - case 3: - vm->agentReg[VM_OFFSET_META_R(0)] = AGENT(a2)->port[0]; - vm->agentReg[VM_OFFSET_META_R(1)] = AGENT(a2)->port[1]; - vm->agentReg[VM_OFFSET_META_R(2)] = AGENT(a2)->port[2]; - break; - - default: - for (i=0; i<arity; i++) { - vm->agentReg[VM_OFFSET_META_R(i)] = AGENT(a2)->port[i]; - } - } - - vm->agentReg[VM_OFFSET_ANNOTATE_L] = a2; - vm->agentReg[VM_OFFSET_ANNOTATE_R] = a1; - -#ifdef COUNT_INTERACTION - vm->NumberOfInteraction++; -#endif - ExecCode(1, vm, &code[2]); - return; + VALUE tmp = a1; + a1 = a2; + a2 = tmp; + goto loop_a2IsFixnum; } // a1 が agent @@ -6561,7 +6598,7 @@ loop_a2IsAgent: if (result == 0) { - if (BASIC(a2)->id <= ID_CONS) { + if (BASIC(a2)->id < START_ID_OF_BUILTIN_AGENT) { // built-in switch (BASIC(a1)->id) { @@ -6569,6 +6606,9 @@ loop_a2IsAgent: case ID_TUPLE0: if (BASIC(a2)->id == ID_TUPLE0) { // [] ~ [] --> nothing +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif freeAgent(a1); freeAgent(a2); return; @@ -6580,6 +6620,9 @@ loop_a2IsAgent: case ID_TUPLE2: if (BASIC(a2)->id == ID_TUPLE2) { // (x1,x2) ~ (y1,y2) --> x1~y1, x2~y2 +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif VALUE a1p1 = AGENT(a1)->port[1]; VALUE a2p1 = AGENT(a2)->port[1]; PUSH(vm, a1p1, a2p1); @@ -6596,6 +6639,9 @@ loop_a2IsAgent: case ID_TUPLE3: if (BASIC(a2)->id == ID_TUPLE3) { // (x1,x2,x3) ~ (y1,y2,y3) --> x1~y1, x2~y2, x3~y3 +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif PUSH(vm, AGENT(a1)->port[2], AGENT(a2)->port[2]); PUSH(vm, AGENT(a1)->port[1], AGENT(a2)->port[1]); @@ -6612,6 +6658,9 @@ loop_a2IsAgent: case ID_TUPLE4: if (BASIC(a2)->id == ID_TUPLE4) { // (x1,x2,x3) ~ (y1,y2,y3) --> x1~y1, x2~y2, x3~y3 +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif PUSH(vm, AGENT(a1)->port[3], AGENT(a2)->port[3]); PUSH(vm, AGENT(a1)->port[2], AGENT(a2)->port[2]); PUSH(vm, AGENT(a1)->port[1], AGENT(a2)->port[1]); @@ -6629,6 +6678,9 @@ loop_a2IsAgent: case ID_TUPLE5: if (BASIC(a2)->id == ID_TUPLE5) { // (x1,x2,x3) ~ (y1,y2,y3) --> x1~y1, x2~y2, x3~y3 +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif PUSH(vm, AGENT(a1)->port[4], AGENT(a2)->port[4]); PUSH(vm, AGENT(a1)->port[3], AGENT(a2)->port[3]); PUSH(vm, AGENT(a1)->port[2], AGENT(a2)->port[2]); @@ -6647,6 +6699,9 @@ loop_a2IsAgent: case ID_NIL: if (BASIC(a2)->id == ID_NIL) { // [] ~ [] --> nothing +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif freeAgent(a1); freeAgent(a2); return; @@ -6658,6 +6713,9 @@ loop_a2IsAgent: case ID_CONS: if (BASIC(a2)->id == ID_CONS) { // a:b ~ c:d --> a~c, b~d +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif VALUE a1p1 = AGENT(a1)->port[1]; VALUE a2p1 = AGENT(a2)->port[1]; PUSH(vm, a1p1, a2p1); @@ -6679,6 +6737,9 @@ loop_a2IsAgent: case ID_NIL: { // App(r,a) >< [] => r~a; +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif VALUE a1p0 = AGENT(a1)->port[0]; VALUE a1p1 = AGENT(a1)->port[1]; freeAgent(a1); @@ -6691,6 +6752,9 @@ loop_a2IsAgent: case ID_CONS: { // App(r,a) >< [x|xs] => r~(*R)[x|w], (*L)App(w,a)~xs; +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif VALUE a1p0 = AGENT(a1)->port[0]; VALUE a2p1 = AGENT(a2)->port[1]; VALUE w = makeName(vm); @@ -6708,7 +6772,118 @@ loop_a2IsAgent: break; // end ID_APPEND - + case ID_MERGER: + switch (BASIC(a2)->id) { + case ID_TUPLE2: + { + // MG(r) ~ (a|b) => *MGp(*r)~a, *MGp(*r)~b +#ifdef COUNT_INTERACTION + vm->NumberOfInteraction++; +#endif + BASIC(a1)->id = ID_MERGER_P; + AGENT(a1)->port[1] = (VALUE)NULL; + AGENT(a1)->port[2] = (VALUE)NULL; + PUSH(vm, a1, AGENT(a2)->port[1]); + PUSH(vm, a1, AGENT(a2)->port[0]); + freeAgent(a2); + return; + + + } + } + break; // end ID_MG + + case ID_MERGER_P: + switch (BASIC(a2)->id) { + case ID_NIL: + // *MGP(r)~[] +#ifndef THREAD + if (AGENT(a1)->port[1] == (VALUE)NULL) { + AGENT(a1)->port[1] = a2; + return; + } else { + VALUE a1p0 = AGENT(a1)->port[0]; + freeAgent(AGENT(a1)->port[1]); + freeAgent(a1); + a1 = a1p0; + goto loop; + } +#else + if (AGENT(a1)->port[2] == (VALUE)NULL) { + if (!(__sync_bool_compare_and_swap(&(AGENT(a1)->port[2]), + NULL, a2))) { + // something exists already + goto loop; + + } else { + return; + } + } else if ((AGENT(a1)->port[2] != (VALUE)NULL) && + (BASIC(AGENT(a1)->port[2])->id == ID_NIL)) { + + VALUE a1p0 = AGENT(a1)->port[0]; + freeAgent(AGENT(a1)->port[2]); + freeAgent(a1); + a1 = a1p0; + goto loop; + } else { + goto loop; + } + +#endif + case ID_CONS: + // *MGP(r)~x:xs => r~x:w, *MGP(w)~xs; + { +#ifndef THREAD + VALUE a1p0 = AGENT(a1)->port[0]; + + VALUE w = makeName(vm); + AGENT(a1)->port[0] = w; + PUSH(vm, a1, AGENT(a2)->port[1]); + + AGENT(a2)->port[1] = w; + a1 = a1p0; + goto loop; +#else + if (AGENT(a1)->port[1] == (VALUE)NULL) { + if (!(__sync_bool_compare_and_swap(&(AGENT(a1)->port[1]), + NULL, + a2))) { + goto loop; + } + + VALUE a1p0 = AGENT(a1)->port[0]; + + VALUE w = makeName(vm); + AGENT(a1)->port[0] = w; + PUSH(vm, a1, AGENT(a2)->port[1]); + + AGENT(a2)->port[1] = w; + + AGENT(a1)->port[1] = (VALUE)NULL; // free the lock + + a1 = a1p0; + + goto loop; + + } else if ((AGENT(a1)->port[2] != (VALUE)NULL) && + (BASIC(AGENT(a1)->port[2])->id == ID_NIL)) { + freeAgent(AGENT(a1)->port[2]); + VALUE a1p0 = AGENT(a1)->port[0]; + freeAgent(a1); + a1 = a1p0; + goto loop; + + } else { + goto loop; + } + + +#endif + } + + } + break; // end ID_MERGER_P } } @@ -6919,14 +7094,18 @@ void WHNFInfo_push_equation(VALUE t1, VALUE t2) { void WHNF_execution_loop() { VALUE t1, t2; + while (PopEQStack(&VM, &t1, &t2)) { + + puts_term(t1); printf("~"); puts_term(t2); puts(""); - if ((NameTable_ckech_if_term_has_gname(t1) == 1) || - (NameTable_ckech_if_term_has_gname(t2) == 1)) { - + if ((NameTable_check_if_term_has_gname(t1) == 1) || + (NameTable_check_if_term_has_gname(t2) == 1)) { + eval_equation(&VM, t1, t2); } else { + WHNFInfo_push_equation(t1, t2); } } @@ -7401,6 +7580,7 @@ int main(int argc, char *argv[]) case '-': case 'h': case '?': + printf("Inpla version %s\n", VERSION); puts("Usage: inpla [options]\n"); puts("Options:"); printf(" -f <filename> Set input file name (Defalut: STDIN)\n"); @@ -7420,7 +7600,7 @@ int main(int argc, char *argv[]) MaxThreadNum); #else - printf(" -w Enable Weak Head Normal Form strategy (Default: false)\n" + printf(" -w Enable Weak Reduction strategy (Default: false)\n" ); @@ -7524,7 +7704,7 @@ int main(int argc, char *argv[]) #ifndef THREAD if (WHNFinfo.enabled) { - printf("Inpla %s (WHNF) : Interaction nets as a programming language", + printf("Inpla %s (Weak Strategy) : Interaction nets as a programming language", VERSION); printf(" [%s]\n", BUILT_DATE); } else { @@ -7578,7 +7758,7 @@ int main(int argc, char *argv[]) linenoiseHistoryLoad(".inpla.history.txt"); - + // the main loop of parsing and execution while(1) { diff --git a/src/linenoise/.gitignore b/src/linenoise/.gitignore new file mode 100644 index 0000000..7ab7825 --- /dev/null +++ b/src/linenoise/.gitignore @@ -0,0 +1,3 @@ +linenoise_example +*.dSYM +history.txt diff --git a/src/name_table.c b/src/name_table.c index f3fae27..3634dd0 100644 --- a/src/name_table.c +++ b/src/name_table.c @@ -418,7 +418,7 @@ void NameTable_free_all() { } -int NameTable_ckech_if_term_has_gname(VALUE term) { +int NameTable_check_if_term_has_gname(VALUE term) { int i; NameList *at; VALUE ptr; diff --git a/src/name_table.h b/src/name_table.h index 588c34d..1ba31a5 100644 --- a/src/name_table.h +++ b/src/name_table.h @@ -45,7 +45,7 @@ IDTYPE NameTable_get_set_id(char *key); void NameTable_puts_all(); void NameTable_free_all(); -int NameTable_ckech_if_term_has_gname(VALUE term); +int NameTable_check_if_term_has_gname(VALUE term); int term_has_keynode(VALUE keynode, VALUE term); int keynode_exists_in_another_term(VALUE keynode, VALUE *connected_from); |
