diff options
| author | Shinya Sato <shinnya.sato@gmail.com> | 2022-01-30 12:57:22 +0900 |
|---|---|---|
| committer | Shinya Sato <shinnya.sato@gmail.com> | 2022-01-30 12:57:22 +0900 |
| commit | 81bf6861fa11c65301a825aff9f4f45c96b68db8 (patch) | |
| tree | 27b5906eb09480dc393fe57b82145033cf220701 | |
| parent | a575f5e005eda74c5c9ba053b944281af5812c91 (diff) | |
| parent | a1124fa3d78b9c97d05a1e6c87fe9c6baf2826df (diff) | |
| download | inpla-81bf6861fa11c65301a825aff9f4f45c96b68db8.tar.gz inpla-81bf6861fa11c65301a825aff9f4f45c96b68db8.zip | |
Merge branch 'develop'
Diffstat (limited to '')
| -rw-r--r-- | Changelog.md | 16 | ||||
| -rw-r--r-- | README.md | 35 | ||||
| -rw-r--r-- | comparison/Inpla/Makefile | 2 | ||||
| -rw-r--r-- | comparison/Inpla/main.sh | 26 | ||||
| -rw-r--r-- | pic/benchmark_reuse_v0.6.2.png | bin | 29824 -> 0 bytes | |||
| -rw-r--r-- | pic/benchmark_reuse_v0.7.0.png | bin | 0 -> 29795 bytes | |||
| -rw-r--r-- | src/ast.c | 4 | ||||
| -rw-r--r-- | src/ast.h | 2 | ||||
| -rw-r--r-- | src/inpla.y | 1439 | ||||
| -rw-r--r-- | src/lex.l | 7 |
10 files changed, 1064 insertions, 467 deletions
diff --git a/Changelog.md b/Changelog.md index 106fca8..84e209f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,21 @@ # Change log +### v0.7.0 (released on 30 January 2022) + +#### New Features: + +- **Logical operators on integers**: Not `!` (`not`), And `&&` (`and`) and Or `||` (`or`) are available. Only `0` is regarded as False and these operators return `1` for Truth, `0` for False. + +- **Bytecode optimisations*: Bytecodes are optimised by methods such as Copy propagation, Delete dead code. In addition, Register0 is used to store comparison results, and conditional branches are performed according to the value of Register0. To prevent those optimisation, comment out the following definition `OPTIMISE_IMCODE` in `src/inpla.y`: + + ``` + #define OPTIMISE_IMCODE // Optimise the intermediate codes + ``` + + + + + ### v0.6.2 (released on 20 January 2022) #### New Features: @@ -6,18 +6,18 @@ 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.6.2 released on **20 January 2022**. (See [Changelog.md](Changelog.md) for details.) +* The current version is 0.7.0 released on **30 January 2022**. (See [Changelog.md](Changelog.md) for details.) - + | | Haskell | SML | Python | Inpla1 | Inpla1_r | Inpla7 | Inpla7_r | | -------------- | :------: | :------: | :----: | :----: | :------: | :----: | :------: | -| ack(3,11) | 2.31 | **0.41** | - | 5.29 | 4.13 | 1.55 | 0.85 | -| fib 38 | 1.60 | **0.26** | 8.49 | 3.90 | 3.63 | 0.67 | 0.61 | -| bsort 40000 | 34.81 | 11.17 | 76.72 | 25.90 | 18.92 | 7.38 | **3.06** | -| isort 40000 | **0.02** | 2.97 | 36.63 | 12.45 | 9.10 | 3.71 | 1.51 | -| qsort 800000 | **0.15** | 1.16 | 97.30 | 3.57 | 1.93 | 0.80 | 0.35 | -| msort 800000 | 0.46 | 1.00 | 98.27 | 2.29 | 1.34 | 0.72 | **0.44** | +| ack(3,11) | 2.31 | **0.41** | - | 5.22 | 3.86 | 1.52 | 0.81 | +| fib 38 | 1.60 | **0.26** | 8.49 | 3.52 | 3.31 | 0.62 | 0.55 | +| bsort 40000 | 34.81 | 11.17 | 76.72 | 25.76 | 18.21 | 7.36 | **2.87** | +| isort 40000 | **0.02** | 2.97 | 36.63 | 11.97 | 8.62 | 3.64 | 1.44 | +| qsort 800000 | **0.15** | 1.16 | 97.30 | 3.55 | 1.87 | 0.82 | 0.35 | +| msort 800000 | 0.46 | 1.00 | 98.27 | 2.29 | 1.34 | 0.60 | **0.33** | - **Comparison in execution time** with other implementations: **Haskell** (GHC version 8.10.7), **Standard ML of New Jersey** v110.74 (interpreter mode) and **Python** 3.8.5 in execution time. @@ -605,7 +605,7 @@ Attributes can be given as the results of arithmetic operation using `where` sta <let-clause> ::= <name> '=' <arithmetic expression> ``` -The symbol of addition, subtraction, multiplication, division and modulo are `+`, `-`, `*`, `/` and `%`, respectively. +The symbol of addition, subtraction, multiplication, division, modulo are `+`, `-`, `*`, `/` and `%`, respectively. Not `!` (`not`), And `&&` (`and`) and Or `||` (`or`) are also available where only `0` is regarded as False and return `1` for Truth. * For instance, the following is an expression using `where`: @@ -820,17 +820,22 @@ Inpla has the following macro: See [Changelog.md](Changelog.md) for details. -### v0.6.0 (released on 9 January 2022) +### v0.7.0 (released on 30 January 2022) #### New Features: -- Introduced new data structure for ring buffers for agents and names: The ring buffers are automatically expanded when all elements of these are used up. Each size starts from 2^18 (=262144), and it will be twice, triple and so on as needed. To adjust the unit size, change the following definition in `src/inpla.y`: +- **Logical operators on integers**: Not `!` (`not`), And `&&` (`and`) and Or `||` (`or`) are available. Only `0` is regarded as False and these operators return `1` for Truth, `0` for False. +- **Bytecode optimisations*: Bytecodes are optimised by methods such as Copy propagation, Delete dead code. See [Changelog.md](Changelog.md) for more details. - ``` - #define HOOP_SIZE (1 << 18) - ``` -- Deleted the execution option `-c` that specifies the size of these ring buffers: This execution option is deleted because these buffers are expanded as needed. + +### v0.6.0 (released on 9 January 2022) + +#### New Features: + +- **Introduced new data structure for ring buffers for agents and names**: The ring buffers are automatically expanded when all elements of these are used up. See [Changelog.md](Changelog.md) for more details. + + ### Logo of Inpla (relased on 27 December 2021) diff --git a/comparison/Inpla/Makefile b/comparison/Inpla/Makefile index 8ca3630..fd03743 100644 --- a/comparison/Inpla/Makefile +++ b/comparison/Inpla/Makefile @@ -2,7 +2,7 @@ all: - sh main.sh + bash main.sh clean: rm -f ./inplaSeq ./inplaPara log-* *~ diff --git a/comparison/Inpla/main.sh b/comparison/Inpla/main.sh index f1e84a9..fbf11c4 100644 --- a/comparison/Inpla/main.sh +++ b/comparison/Inpla/main.sh @@ -1,19 +1,19 @@ -#!/bin/sh +#!/bin/bash -./sptestInpla.sh src/fib-38.in -./sptestInpla.sh src/fib-38-reuse.in +bash ./sptestInpla.sh src/fib-38.in +bash ./sptestInpla.sh src/fib-38-reuse.in -./sptestInpla.sh src/ack-stream_3-11.in -./sptestInpla.sh src/ack-stream_3-11-reuse.in +bash ./sptestInpla.sh src/ack-stream_3-11.in +bash ./sptestInpla.sh src/ack-stream_3-11-reuse.in -./sptestInpla.sh src/bsort-40000.in -./sptestInpla.sh src/bsort-40000-reuse.in +bash ./sptestInpla.sh src/bsort-40000.in +bash ./sptestInpla.sh src/bsort-40000-reuse.in -./sptestInpla.sh src/isort-40000.in -./sptestInpla.sh src/isort-40000-reuse.in +bash ./sptestInpla.sh src/isort-40000.in +bash ./sptestInpla.sh src/isort-40000-reuse.in -./sptestInpla.sh src/qsort-800000.in -./sptestInpla.sh src/qsort-800000-reuse.in +bash ./sptestInpla.sh src/qsort-800000.in +bash ./sptestInpla.sh src/qsort-800000-reuse.in -./sptestInpla.sh src/msort-800000.in -./sptestInpla.sh src/msort-800000-reuse.in +bash ./sptestInpla.sh src/msort-800000.in +bash ./sptestInpla.sh src/msort-800000-reuse.in diff --git a/pic/benchmark_reuse_v0.6.2.png b/pic/benchmark_reuse_v0.6.2.png Binary files differdeleted file mode 100644 index fc1af62..0000000 --- a/pic/benchmark_reuse_v0.6.2.png +++ /dev/null diff --git a/pic/benchmark_reuse_v0.7.0.png b/pic/benchmark_reuse_v0.7.0.png Binary files differnew file mode 100644 index 0000000..5d029cd --- /dev/null +++ b/pic/benchmark_reuse_v0.7.0.png @@ -265,7 +265,9 @@ void ast_puts(Ast *p) { // extension "TUPLE", "PPAIR", "INT", "LD", "ADD", "SUB", "MUL", "DIV", "MOD", - "LT", "LE", "EQ", "NE", "UNM", + "LT", "LE", "EQ", "NE", "UNM", "AND", "OR", "NOT", + + "CONS", "NIL", "OPCONS", "RAND", "SRAND", @@ -18,7 +18,7 @@ typedef enum { // operation AST_INT, AST_LD, AST_PLUS, AST_SUB, AST_MUL, AST_DIV, AST_MOD, - AST_LT, AST_LE, AST_EQ, AST_NE, AST_UNM, + AST_LT, AST_LE, AST_EQ, AST_NE, AST_UNM, AST_AND, AST_OR, AST_NOT, // for built-in lists AST_CONS, AST_NIL, AST_OPCONS, diff --git a/src/inpla.y b/src/inpla.y index 90b7278..5303bdd 100644 --- a/src/inpla.y +++ b/src/inpla.y @@ -20,6 +20,8 @@ // Configuration --------------------------------------------------- #define COUNT_INTERACTION // Count interaction. #define EXPANDABLE_HEAP // Expandable heaps for agents and names +#define OPTIMISE_IMCODE // Optimise the intermediate codes + //#define VERBOSE_NODE_USE // Put memory usage of agents and names. //#define VERBOSE_HOOP_EXPANSION // Put messages when hoops are expanded. @@ -35,8 +37,8 @@ //#define COUNT_MKAGENT // count of execution fo mkagent -#define VERSION "0.6.2" -#define BUILT_DATE "20 Jan. 2022" +#define VERSION "0.7.0" +#define BUILT_DATE "30 Jan. 2022" // ------------------------------------------------------------------ @@ -157,7 +159,8 @@ static char *Errormsg = NULL; %token ANNOTATE_L ANNOTATE_R -%token PIPE AMP LD EQUAL NE GT GE LT LE +%token PIPE +%token NOT AND OR LD EQUAL NE GT GE LT LE %token ADD SUB MUL DIV MOD INT LET IN END IF THEN ELSE ANY WHERE RAND DEF %token INTERFACE IFCE PRNAT FREE EXIT %token END_OF_FILE USE @@ -168,7 +171,7 @@ rule ap aplist stm stmlist_nondelimiter stmlist -expr additive_expr equational_expr relational_expr unary_expr +expr additive_expr equational_expr logical_expr relational_expr unary_expr multiplicative_expr primary_expr agent_tuple agent_list agent_cons bodyguard bd_else bd_elif bd_compound if_sentence if_compound @@ -483,9 +486,16 @@ expr ; equational_expr +: logical_expr +| equational_expr EQUAL logical_expr { $$ = ast_makeAST(AST_EQ, $1, $3); } +| equational_expr NE logical_expr { $$ = ast_makeAST(AST_NE, $1, $3); } + +logical_expr : relational_expr -| equational_expr EQUAL relational_expr { $$ = ast_makeAST(AST_EQ, $1, $3); } -| equational_expr NE relational_expr { $$ = ast_makeAST(AST_NE, $1, $3); } +| NOT relational_expr { $$ = ast_makeAST(AST_NOT, $2, NULL); } +| logical_expr AND relational_expr { $$ = ast_makeAST(AST_AND, $1, $3); } +| logical_expr OR relational_expr { $$ = ast_makeAST(AST_OR, $1, $3); } +; relational_expr : additive_expr @@ -1335,13 +1345,21 @@ void puts_eqlist(EQList *at) { /********************************** VIRTUAL MACHINE *********************************/ -#define VM_LOCALVAR_SIZE 200 +#define VM_REG_SIZE 128 + +/* #define VM_OFFSET_META_L(a) (a) #define VM_OFFSET_META_R(a) (MAX_PORT+(a)) #define VM_OFFSET_ANNOTATE_L (MAX_PORT*2) #define VM_OFFSET_ANNOTATE_R (MAX_PORT*2+1) #define VM_OFFSET_LOCALVAR (MAX_PORT*2+2) +*/ +#define VM_OFFSET_META_L(a) (a+1) +#define VM_OFFSET_META_R(a) (MAX_PORT+1+(a)) +#define VM_OFFSET_ANNOTATE_L (MAX_PORT*2+1) +#define VM_OFFSET_ANNOTATE_R (MAX_PORT*2+2) +#define VM_OFFSET_LOCALVAR (MAX_PORT*2+2+1) typedef struct { @@ -1353,20 +1371,21 @@ typedef struct { int nextPtr_eqStack; int eqStack_size; +#ifdef COUNT_INTERACTION + unsigned int count_interaction; +#endif - // code execution - VALUE reg[VM_LOCALVAR_SIZE+(MAX_PORT*2 + 2)]; - // flag - // VALUE flag; + // register + // VALUE reg[VM_REG_SIZE+(MAX_PORT*2 + 2)]; + // VALUE reg[VM_REG_SIZE]; + VALUE *reg; - + +#ifdef THREAD unsigned int id; -#ifdef COUNT_INTERACTION - unsigned int count_interaction; - #endif - + } VirtualMachine; #ifdef COUNT_INTERACTION @@ -1397,6 +1416,8 @@ void VM_Buffer_Init(VirtualMachine *vm) { vm->nameHeap.last_alloc_list = HoopList_New_forName(); vm->nameHeap.last_alloc_list->next = vm->nameHeap.last_alloc_list; vm->nameHeap.last_alloc_idx = 0; + + vm->reg = malloc(sizeof(VALUE) * VM_REG_SIZE); } #else @@ -1414,6 +1435,7 @@ void VM_InitBuffer(VirtualMachine *vm, int size) { //vm->nameHeap.lastAlloc = 0; vm->nameHeap.size = size; + vm->reg = malloc(sizeof(VALUE) * VM_REG_SIZE); } #endif @@ -1885,15 +1907,28 @@ typedef enum { OP_MUL, OP_DIV, OP_MOD, + OP_LT, OP_LE, OP_EQ, OP_EQI, OP_NE, + + OP_LT_R0, + OP_LE_R0, + OP_EQ_R0, + OP_EQI_R0, + OP_NE_R0, + + OP_JMPEQ0, + OP_JMPEQ0_R0, + OP_JMP, + OP_JMPNEQ0, + OP_JMPCNCT_CONS, OP_JMPCNCT, - OP_JMP, + OP_UNM, OP_RAND, @@ -1904,7 +1939,8 @@ typedef enum { NOP, // This will be used for translation from intermediate codes to Bytecodes - VOID_CODE + LABEL, + DEAD_CODE } Code; @@ -1912,6 +1948,22 @@ typedef enum { static void* CodeAddr[NOP+1]; +//void *ExecCode(int arg, VirtualMachine *vm, void **code); +void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code); + +void CodeAddr_init(void) { + // Set CodeAddr + void **table; + table = ExecCode(0, NULL, NULL); + for (int i=0; i<NOP; i++) { + CodeAddr[i] = table[i]; + } +} + + + + + typedef enum { NB_NAME=0, NB_META, @@ -2026,7 +2078,7 @@ typedef struct { // Index for local and global names in Regs int localNamePtr; // It starts from VM_OFFSET_LOCALVAR - int vmStackSize; // the array size of the Regs. + int vmRegSize; // the array size of the Regs. // For rule agents @@ -2035,6 +2087,9 @@ typedef struct { // ruleAgentL, ruleAgentR int annotateL, annotateR; // `Annotation properties' such as (*L) (*R) (int) + + // labels + int label; } CmEnvironment; // The annotation properties @@ -2045,25 +2100,6 @@ typedef struct { static CmEnvironment CmEnv; -//void *ExecCode(int arg, VirtualMachine *vm, void **code); -void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code); - - -void CmEnv_clear_all(void); - - -void CmEnv_Init(int vm_heapsize) { - CmEnv.vmStackSize = vm_heapsize; - - void **table; - table = ExecCode(0, NULL, NULL); - for (int i=0; i<NOP; i++) { - CodeAddr[i] = table[i]; - } - - CmEnv_clear_all(); -} - static inline void CmEnv_clear_localnamePtr(void) { @@ -2103,6 +2139,9 @@ void CmEnv_clear_all(void) // reset the index of storage for imtermediate codes. IMCode_Init(); + + // reset the index of labels; + CmEnv.label = 0; } void CmEnv_clear_keeping_rule_properties(void) @@ -2121,11 +2160,16 @@ void CmEnv_clear_keeping_rule_properties(void) // reset the beginning number for local vars. CmEnv_clear_localnamePtr(); + /* // reset the index of storage for imtermediate codes. IMCode_Init(); + */ } +int CmEnv_get_newlabel(void) { + return CmEnv.label++; +} int CmEnv_set_symbol_as_name(char *name) { @@ -2147,8 +2191,8 @@ int CmEnv_set_symbol_as_name(char *name) { result = CmEnv.localNamePtr; CmEnv.localNamePtr++; - if (CmEnv.localNamePtr > CmEnv.vmStackSize) { - puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded CmEnv.vmStackSize."); + if (CmEnv.localNamePtr > VM_REG_SIZE) { + puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded VM_REG_SIZE."); exit(-1); } @@ -2195,8 +2239,8 @@ int CmEnv_set_as_INTVAR(char *name) { } CmEnv.localNamePtr++; - if (CmEnv.localNamePtr > CmEnv.vmStackSize) { - puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded CmEnv.vmStackSize."); + if (CmEnv.localNamePtr > VM_REG_SIZE) { + puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded VM_REG_SIZE."); exit(-1); } @@ -2237,8 +2281,8 @@ int CmEnv_newreg(void) { int result; result = CmEnv.localNamePtr; CmEnv.localNamePtr++; - if (CmEnv.localNamePtr > CmEnv.vmStackSize) { - puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded CmEnv.vmStackSize."); + if (CmEnv.localNamePtr > VM_REG_SIZE) { + puts("SYSTEM ERROR: CmEnv.localNamePtr exceeded VM_REG_SIZE."); exit(-1); } @@ -2307,47 +2351,209 @@ void CmEnv_Retrieve_GNAME(void) { } -int CmEnv_Generate_VMCode(void **code, int offset) { - int ptr = offset; +int CmEnv_Optimise_VMCode_CopyPropagation(int target_imcode_addr) { + struct IMCode_tag *imcode; + int load_from, load_to; + load_from = IMCode[target_imcode_addr].operand2; + load_to = IMCode[target_imcode_addr].operand1; - for (int i=0; i<IMCode_n; i++) { + for (int i=target_imcode_addr+1; i<IMCode_n; i++) { imcode = &IMCode[i]; switch (imcode->opcode) { case MKNAME: + case MKGNAME: + break; + + case MKAGENT5: + case REUSEAGENT5: + if (imcode->operand7 == load_to) { + imcode->operand7 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + case MKAGENT4: + case REUSEAGENT4: + if (imcode->operand6 == load_to) { + imcode->operand6 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + case MKAGENT3: + case REUSEAGENT3: + if (imcode->operand5 == load_to) { + imcode->operand5 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + case MKAGENT2: + case REUSEAGENT2: + if (imcode->operand4 == load_to) { + imcode->operand4 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + case MKAGENT1: + case REUSEAGENT1: + if (imcode->operand3 == load_to) { + imcode->operand3 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + case MKAGENT0: + case REUSEAGENT0: + break; + + + case PUSH: + case MYPUSH: + if (imcode->operand1 == load_to) { + imcode->operand1 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + if (imcode->operand2 == load_to) { + imcode->operand2 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + case OP_JMPEQ0: + case OP_JMPNEQ0: + case OP_JMPCNCT_CONS: + case OP_JMPCNCT: + case PUSHI: + if (imcode->operand1 == load_to) { + imcode->operand1 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + case OP_MUL: + case OP_DIV: + case OP_MOD: + case OP_LT: + case OP_LE: + case OP_EQ: + case OP_NE: + case OP_ADD: + case OP_SUB: + if (imcode->operand2 == load_to) { + imcode->operand2 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + if (imcode->operand3 == load_to) { + imcode->operand3 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + case OP_SUBI: + case OP_EQI: + if (imcode->operand2 == load_to) { + imcode->operand2 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + case OP_LT_R0: + case OP_LE_R0: + case OP_EQ_R0: + case OP_NE_R0: + if (imcode->operand1 == load_to) { + imcode->operand1 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + if (imcode->operand2 == load_to) { + imcode->operand2 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + case OP_EQI_R0: + if (imcode->operand1 == load_to) { + imcode->operand1 = load_from; + IMCode[target_imcode_addr].opcode = DEAD_CODE; + return 1; + } + break; + + } + + } + + return 0; + +} + + +#define MAX_LABEL 50 +#define MAX_BACKPATCH MAX_LABEL*2 +int CmEnv_generate_VMcode(void **code) { + int addr = 0; + struct IMCode_tag *imcode; + + int label_table[MAX_LABEL]; + int backpatch_num = 0; + int backpatch_table[MAX_BACKPATCH]; + + for (int i=0; i<IMCode_n; i++) { + imcode = &IMCode[i]; + +#ifdef OPTIMISE_IMCODE + + // optimisation + // Copy Propagation for LOAD reg1, reg2 --> [reg2/reg1] + // and Dead Code Optimisation + if (imcode->opcode == LOAD) { + if (CmEnv_Optimise_VMCode_CopyPropagation(i)) { + continue; + } + } +#endif + + switch (imcode->opcode) { + case MKNAME: // printf("MKNAME var%d\n", imcode->operand1); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; break; case MKGNAME: // printf("MKGNAME var%d sym:%d (as `%s')\n", // imcode->operand1, imcode->operand2, // CmEnv.bind[imcode->operand2].name); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = CmEnv.bind[imcode->operand2].name; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = CmEnv.bind[imcode->operand2].name; break; case MKAGENT0: case REUSEAGENT0: // printf("MKAGENT0 var%d id:%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; break; case MKAGENT1: case REUSEAGENT1: // printf("MKAGENT1 var%d id:%d var%d\n", // imcode->operand1, imcode->operand2, imcode->operand3); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; break; case MKAGENT2: @@ -2355,11 +2561,11 @@ int CmEnv_Generate_VMCode(void **code, int offset) { // printf("MKAGENT2 var%d id:%d var%d var%d\n", // imcode->operand1, imcode->operand2, // imcode->operand3, imcode->operand4); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; - code[ptr++] = (void *)(unsigned long)imcode->operand4; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = (void *)(unsigned long)imcode->operand4; break; case MKAGENT3: @@ -2367,12 +2573,12 @@ int CmEnv_Generate_VMCode(void **code, int offset) { // printf("MKAGENT3 var%d id:%d var%d var%d var%d\n", // imcode->operand1, imcode->operand2, // imcode->operand3, imcode->operand4, imcode->operand5); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; - code[ptr++] = (void *)(unsigned long)imcode->operand4; - code[ptr++] = (void *)(unsigned long)imcode->operand5; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = (void *)(unsigned long)imcode->operand4; + code[addr++] = (void *)(unsigned long)imcode->operand5; break; case MKAGENT4: @@ -2380,13 +2586,13 @@ int CmEnv_Generate_VMCode(void **code, int offset) { // printf("MKAGENT3 var%d id:%d var%d var%d var%d\n", // imcode->operand1, imcode->operand2, // imcode->operand3, imcode->operand4, imcode->operand5); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; - code[ptr++] = (void *)(unsigned long)imcode->operand4; - code[ptr++] = (void *)(unsigned long)imcode->operand5; - code[ptr++] = (void *)(unsigned long)imcode->operand6; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = (void *)(unsigned long)imcode->operand4; + code[addr++] = (void *)(unsigned long)imcode->operand5; + code[addr++] = (void *)(unsigned long)imcode->operand6; break; case MKAGENT5: @@ -2394,29 +2600,49 @@ int CmEnv_Generate_VMCode(void **code, int offset) { // printf("MKAGENT3 var%d id:%d var%d var%d var%d\n", // imcode->operand1, imcode->operand2, // imcode->operand3, imcode->operand4, imcode->operand5); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; - code[ptr++] = (void *)(unsigned long)imcode->operand4; - code[ptr++] = (void *)(unsigned long)imcode->operand5; - code[ptr++] = (void *)(unsigned long)imcode->operand6; - code[ptr++] = (void *)(unsigned long)imcode->operand7; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = (void *)(unsigned long)imcode->operand4; + code[addr++] = (void *)(unsigned long)imcode->operand5; + code[addr++] = (void *)(unsigned long)imcode->operand6; + code[addr++] = (void *)(unsigned long)imcode->operand7; break; case PUSH: case MYPUSH: case LOAD: - case OP_JMPEQ0: case OP_JMPCNCT_CONS: // printf("PUSH var%d var%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + break; + + + + case OP_JMPEQ0: + case OP_JMPNEQ0: + // JMPEQ0 reg label + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + + backpatch_table[backpatch_num++] = addr; + code[addr++] = (void *)(unsigned long)imcode->operand2; + break; + + + case OP_JMPEQ0_R0: + code[addr++] = CodeAddr[imcode->opcode]; + + backpatch_table[backpatch_num++] = addr; + code[addr++] = (void *)(unsigned long)imcode->operand1; break; + case OP_ADD: case OP_SUB: case OP_MUL: @@ -2428,19 +2654,30 @@ int CmEnv_Generate_VMCode(void **code, int offset) { case OP_NE: case OP_SUBI: case OP_EQI: - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; break; + + case OP_LT_R0: + case OP_LE_R0: + case OP_EQ_R0: + case OP_NE_R0: + case OP_EQI_R0: + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + break; + case PUSHI: // printf("PUSH var%d $%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)INT2FIX(imcode->operand2); + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)INT2FIX(imcode->operand2); break; @@ -2450,16 +2687,16 @@ int CmEnv_Generate_VMCode(void **code, int offset) { case RET_FREE_LR: case LOOP: case NOP: - code[ptr++] = CodeAddr[imcode->opcode]; + code[addr++] = CodeAddr[imcode->opcode]; break; case LOADI: // printf("LOADI var%d $%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)INT2FIX(imcode->operand2); + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)INT2FIX(imcode->operand2); break; @@ -2467,54 +2704,77 @@ int CmEnv_Generate_VMCode(void **code, int offset) { case LOOP_RREC2: // printf("LOOP_RREC1 var%d\n", // imcode->operand1); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; break; case LOADP: case OP_JMPCNCT: // printf("LOADP var%d var%d[%d]\n", // imcode->operand1, imcode->operand2, imcode->operand3); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; - code[ptr++] = (void *)(unsigned long)imcode->operand3; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = (void *)(unsigned long)imcode->operand3; break; case OP_JMP: // printf("JMP $%d\n", // imcode->operand1); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = CodeAddr[imcode->opcode]; + + backpatch_table[backpatch_num++] = addr; + code[addr++] = (void *)(unsigned long)imcode->operand1; break; case OP_UNM: case OP_RAND: // printf("UNM var%d $%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; break; case CNCTGN: case SUBSTGN: // printf("CNCTGN var%d $%d\n", // imcode->operand1, imcode->operand2); - code[ptr++] = CodeAddr[imcode->opcode]; - code[ptr++] = (void *)(unsigned long)imcode->operand1; - code[ptr++] = (void *)(unsigned long)imcode->operand2; + code[addr++] = CodeAddr[imcode->opcode]; + code[addr++] = (void *)(unsigned long)imcode->operand1; + code[addr++] = (void *)(unsigned long)imcode->operand2; + break; + + + case DEAD_CODE: + break; + + case LABEL: + if (imcode->operand1 > MAX_LABEL) { + printf("Critical Error: Label number overfllow."); + exit(-1); + } + label_table[imcode->operand1] = addr; break; default: - printf("Error[CmEnv_Generate_VMCode]: %d does not match any opcode\n", + printf("Error[CmEnv_generate_VMcode]: %d does not match any opcode\n", imcode->opcode); exit(-1); } } - return (ptr-offset); + + // two pass for label + for (int i=0; i<backpatch_num; i++) { + int hole_addr = backpatch_table[i]; + int jmp_label = (unsigned long)code[hole_addr]; + code[hole_addr] = (void *)(unsigned long) + (label_table[jmp_label]-(hole_addr+1)); + } + + return addr; } @@ -2715,36 +2975,68 @@ void IMCode_Puts(int n) { printf("MOD var%d var%d var%d\n", imcode->operand1, imcode->operand2, imcode->operand3); break; - + + case OP_LT: printf("LT var%d var%d var%d\n", imcode->operand1, imcode->operand2, imcode->operand3); + break; + case OP_LT_R0: + printf("LT_R0 var%d var%d\n", + imcode->operand1, imcode->operand2); break; case OP_LE: printf("LE var%d var%d var%d\n", imcode->operand1, imcode->operand2, imcode->operand3); break; + case OP_LE_R0: + printf("LE_R0 var%d var%d\n", + imcode->operand1, imcode->operand2); + break; case OP_EQ: printf("EQ var%d var%d var%d\n", imcode->operand1, imcode->operand2, imcode->operand3); break; + case OP_EQ_R0: + printf("EQ_R0 var%d var%d\n", + imcode->operand1, imcode->operand2); + break; case OP_EQI: printf("EQI var%d var%d $%d\n", imcode->operand1, imcode->operand2, imcode->operand3); break; + case OP_EQI_R0: + printf("EQI_R0 var%d $%d\n", + imcode->operand1, imcode->operand2); + break; case OP_NE: printf("NE var%d var%d var%d\n", imcode->operand1, imcode->operand2, imcode->operand3); break; + case OP_NE_R0: + printf("NE_R0 var%d var%d\n", + imcode->operand1, imcode->operand2); + break; + + + case OP_JMPNEQ0: + printf("JMPNEQ0 var%d LABEL%d\n", + imcode->operand1, imcode->operand2); + break; case OP_JMPEQ0: - printf("JMPEQ0 var%d $%d\n", + printf("JMPEQ0 var%d LABEL%d\n", imcode->operand1, imcode->operand2); break; + + case OP_JMPEQ0_R0: + printf("JMPEQ0_RO LABEL%d\n", + imcode->operand1); + break; case OP_JMPCNCT_CONS: printf("JMPCNCT_CONS var%d $%d\n", @@ -2757,7 +3049,7 @@ void IMCode_Puts(int n) { break; case OP_JMP: - printf("JMP $%d\n", + printf("JMP LABEL%d\n", imcode->operand1); break; @@ -2785,6 +3077,15 @@ void IMCode_Puts(int n) { printf("NOP\n"); break; + case DEAD_CODE: + printf("DEAD\n"); + break; + + case LABEL: + printf(":LABEL%d\n", + imcode->operand1); + break; + default: printf("CODE %d %d %d %d %d %d\n", imcode->operand1, imcode->operand2, imcode->operand3, @@ -3039,13 +3340,6 @@ void PutsCodeN(void **code, int n) { (unsigned long)code[i+3]); i+=3; - } else if (code[i] == CodeAddr[OP_LE]) { - printf("le var%lu var%lu var%lu\n", - (unsigned long)code[i+1], - (unsigned long)code[i+2], - (unsigned long)code[i+3]); - i+=3; - } else if (code[i] == CodeAddr[OP_EQ]) { printf("eq var%lu var%lu var%lu\n", (unsigned long)code[i+1], @@ -3066,6 +3360,42 @@ void PutsCodeN(void **code, int n) { (unsigned long)code[i+2], (unsigned long)code[i+3]); i+=3; + + } else if (code[i] == CodeAddr[OP_LT_R0]) { + printf("lt_r0 var%lu var%lu\n", + (unsigned long)code[i+1], + (unsigned long)code[i+2]); + i+=2; + + } else if (code[i] == CodeAddr[OP_LE_R0]) { + printf("le_r0 var%lu var%lu\n", + (unsigned long)code[i+1], + (unsigned long)code[i+2]); + i+=2; + + } else if (code[i] == CodeAddr[OP_EQ_R0]) { + printf("eq_r0 var%lu var%lu\n", + (unsigned long)code[i+1], + (unsigned long)code[i+2]); + i+=2; + + } else if (code[i] == CodeAddr[OP_EQI_R0]) { + printf("eqi_r0 var%lu var%ld\n", + (unsigned long)code[i+1], + (long int)code[i+2]); + i+=2; + + } else if (code[i] == CodeAddr[OP_NE_R0]) { + printf("ne_r0 var%lu var%lu\n", + (unsigned long)code[i+1], + (unsigned long)code[i+2]); + i+=2; + + } else if (code[i] == CodeAddr[OP_JMPNEQ0]) { + printf("jmpneq0 var%lu $%lu\n", + (unsigned long)code[i+1], + (unsigned long)code[i+2]); + i+=2; } else if (code[i] == CodeAddr[OP_JMPEQ0]) { printf("jmpeq0 var%lu $%lu\n", @@ -3073,6 +3403,11 @@ void PutsCodeN(void **code, int n) { (unsigned long)code[i+2]); i+=2; + } else if (code[i] == CodeAddr[OP_JMPEQ0_R0]) { + printf("jmpeq0_r0 $%lu\n", + (unsigned long)code[i+1]); + i+=1; + } else if (code[i] == CodeAddr[OP_JMPCNCT_CONS]) { printf("jmpcnct_cons var%lu $%lu\n", (unsigned long)code[i+1], @@ -3188,7 +3523,7 @@ int is_expr(Ast *ptr) { int CompileExprFromAst(Ast *ptr, int target) { - + if (ptr == NULL) { return 1; } @@ -3276,11 +3611,109 @@ int CompileExprFromAst(Ast *ptr, int target) { } IMCode_genCode3(opcode, target, newreg, newreg2); - return 1; + return 1; + break; + } + case AST_AND: { + // compilation of expr1 && expr2 + + // if (expr1 == 0) goto L1; + // if (expr2 == 0) goto L1; + // target = 1; + // goto L2; + // L1: + // target = 0; + // L2; + + int newreg = CmEnv_newreg(); + if (!CompileExprFromAst(ptr->left, newreg)) return 0; + + int label1 = CmEnv_get_newlabel(); + IMCode_genCode2(OP_JMPEQ0, newreg, label1); + + int newreg2 = CmEnv_newreg(); + if (!CompileExprFromAst(ptr->right, newreg2)) return 0; + IMCode_genCode2(OP_JMPEQ0, newreg2, label1); + + IMCode_genCode2(LOADI, target, 1); + + int label2 = CmEnv_get_newlabel(); + IMCode_genCode1(OP_JMP, label2); + + IMCode_genCode1(LABEL, label1); + IMCode_genCode2(LOADI, target, 0); + + IMCode_genCode1(LABEL, label2); + + return 1; break; } + case AST_OR: { + // compilation of expr1 || expr2 + + // calc expr1 + // if (expr1 != 0) goto L1; + // if (expr2 != 0) goto L1; + // target = 0; + // goto L2; + // L1: + // target = 1; + // L2; + + int newreg = CmEnv_newreg(); + if (!CompileExprFromAst(ptr->left, newreg)) return 0; + + int label1 = CmEnv_get_newlabel(); + IMCode_genCode2(OP_JMPNEQ0, newreg, label1); + + int newreg2 = CmEnv_newreg(); + if (!CompileExprFromAst(ptr->right, newreg2)) return 0; + IMCode_genCode2(OP_JMPNEQ0, newreg2, label1); + + IMCode_genCode2(LOADI, target, 0); + + int label2 = CmEnv_get_newlabel(); + IMCode_genCode1(OP_JMP, label2); + + IMCode_genCode1(LABEL, label1); + IMCode_genCode2(LOADI, target, 1); + + IMCode_genCode1(LABEL, label2); + + return 1; + break; + } + case AST_NOT: { + // compilation of !(expr1) + // if (expr1 == 0) goto L1; + // target = 0; + // goto L2; + // L1: + // target = 1; + // L2; + + int newreg = CmEnv_newreg(); + if (!CompileExprFromAst(ptr->left, newreg)) return 0; + + int label1 = CmEnv_get_newlabel(); + IMCode_genCode2(OP_JMPEQ0, newreg, label1); + + IMCode_genCode2(LOADI, target, 0); + + int label2 = CmEnv_get_newlabel(); + IMCode_genCode1(OP_JMP, label2); + + IMCode_genCode1(LABEL, label1); + IMCode_genCode2(LOADI, target, 1); + + IMCode_genCode1(LABEL, label2); + + return 1; + break; + } + default: - puts("System ERROR: Wrong AST was given to CompileExpr."); + puts("System ERROR: Wrong AST was given to CompileExpr.\n"); return 0; } @@ -4253,11 +4686,12 @@ int getRuleAgentID(Ast *ruleAgent) { -int CompileIfSentenceFromAST(Ast *if_sentence_top, - void **code, int offset_code) { - // return - // generated codesize - // -1 : compile error +//int CompileIfSentenceFromAST(Ast *if_sentence_top, +// void **code, int offset_code) { + +int CompileIfSentenceFromAST(Ast *if_sentence_top) { + // return 1: success + // 0: compile error // <if-sentence> ::= (AST_IF guard (AST_BRANCH <then> <else>)) // | <body> @@ -4266,8 +4700,6 @@ int CompileIfSentenceFromAST(Ast *if_sentence_top, Ast *if_sentence; - int generated_codesize; // コンパイルで生成されたコード数保存用 - if_sentence = if_sentence_top; CmEnv_clear_keeping_rule_properties(); @@ -4277,83 +4709,103 @@ int CompileIfSentenceFromAST(Ast *if_sentence_top, // 通常コンパイル Ast *body = if_sentence; - if (!CompileBodyFromAst(body)) return -1; + if (!CompileBodyFromAst(body)) return 0; Compile_Put_Ret_ForRuleBody(); CmEnv_Retrieve_GNAME(); - generated_codesize = CmEnv_Generate_VMCode(code, offset_code); - if (generated_codesize < 0) { - puts("System ERROR: Generated codes were too long."); - return -1; - } - if (!CmEnv_check_meta_occur_once()) { printf("in the rule:\n %s >< %s.\n", IdTable_get_name(CmEnv.idL), IdTable_get_name(CmEnv.idR)); - return -1; + return 0; } - return generated_codesize; + return 1; } else { // if_sentence Ast *guard, *then_branch, *else_branch; - int label; // 飛び先指定用 + int label; // jump label - int offset = offset_code; guard = if_sentence->left; then_branch = if_sentence->right->left; else_branch = if_sentence->right->right; - // Gurad のコンパイル + // Compilation of Guard expressions int newreg = CmEnv_newreg(); if (!CompileExprFromAst(guard, newreg)) return -1; - - // CmEnv_Retrieve_GNAME(); - generated_codesize = CmEnv_Generate_VMCode(code, offset_code); - offset += generated_codesize; - //JMPEQ0 用コードを作成 - code[offset++] = CodeAddr[OP_JMPEQ0]; - code[offset++] = (void *)(unsigned long)newreg; - label = offset++; // 飛び先を格納するアドレスを記憶しておく +#ifdef OPTIMISE_IMCODE + // optimisation for R0 + int opt = 0; + struct IMCode_tag *imcode = &IMCode[IMCode_n-1]; + switch(imcode->opcode) { + case OP_LT: + imcode->opcode = OP_LT_R0; + opt=1; + break; - // then_branch のコンパイル - CmEnv_clear_localnamePtr(); // 局所変数としての reg番号を初期化 + case OP_LE: + imcode->opcode = OP_LE_R0; + opt=1; + break; - generated_codesize = CompileIfSentenceFromAST(then_branch, code, offset); - if (generated_codesize < 0) return -1; - - offset += generated_codesize; + case OP_EQ: + imcode->opcode = OP_EQ_R0; + opt=1; + break; + + case OP_EQI: + imcode->opcode = OP_EQI_R0; + opt=1; + break; - if (offset > MAX_CODE_SIZE) { - puts("System ERROR: Generated codes were too big."); - return -1; + case OP_NE: + imcode->opcode = OP_NE_R0; + opt=1; + } + + if (opt == 1) { + imcode->operand1 = imcode->operand2; + imcode->operand2 = imcode->operand3; } +#endif - // JMPEQ0 のとび先を格納(相対ジャンプ) - code[label]=(void *)(unsigned long)generated_codesize; + // CmEnv_Retrieve_GNAME(); // <- no need for guard expressions - // else_branch のコンパイル + // Generate JMPEQ0 for VM + label = CmEnv_get_newlabel(); +#ifdef OPTIMISE_IMCODE + if (opt != 1) { + IMCode_genCode2(OP_JMPEQ0, newreg, label); + + } else { + IMCode_genCode1(OP_JMPEQ0_R0, label); + } +#else + IMCode_genCode2(OP_JMPEQ0, newreg, label); +#endif + + + // Compilation of then_branch CmEnv_clear_localnamePtr(); // 局所変数としての reg番号を初期化 + if (!CompileIfSentenceFromAST(then_branch)) return 0; + - generated_codesize = CompileIfSentenceFromAST(else_branch, code, offset); - if (generated_codesize < 0) return -1; + IMCode_genCode1(LABEL, label); - offset += generated_codesize; - if (offset > MAX_CODE_SIZE) { - puts("System ERROR: Generated codes were too big."); - return -1; - } - return offset - offset_code; + // else_branch のコンパイル + CmEnv_clear_localnamePtr(); // 局所変数としての reg番号を初期化 + if (!CompileIfSentenceFromAST(else_branch)) return 0; + + return 1; } @@ -4377,7 +4829,7 @@ int makeRule(Ast *ast) { Ast *ruleL, *ruleR, *if_sentence; void* code[MAX_CODE_SIZE]; - int code_offset=0; + int gencode_num=0; ruleL = ast->left->left; ruleR = ast->left->right; @@ -4477,32 +4929,31 @@ int makeRule(Ast *ast) { setAnnotateLR(VM_OFFSET_ANNOTATE_R, VM_OFFSET_ANNOTATE_L); } - { - int arity; - - // IMPORTANT: - // At the first two codes, arities of idL and idR are stored. - if (idL == ID_INT) { - arity = 0; - } else { - arity = getArityFromAST(ruleL); - } - IdTable_set_arity(idL, arity); - code[0] = (void *)(unsigned long)arity; - - if (idR == ID_INT) { - arity = 0; - } else { - arity = getArityFromAST(ruleR); - } - IdTable_set_arity(idR, arity); - code[1] = (void *)(unsigned long)arity; - - code_offset = 2; + int arity; + + // IMPORTANT: + // The first two codes stores arities of idL and idR, respectively. + if (idL == ID_INT) { + arity = 0; + } else { + arity = getArityFromAST(ruleL); + } + IdTable_set_arity(idL, arity); + code[0] = (void *)(unsigned long)arity; + + if (idR == ID_INT) { + arity = 0; + } else { + arity = getArityFromAST(ruleR); } + IdTable_set_arity(idR, arity); + code[1] = (void *)(unsigned long)arity; + gencode_num = 2; + + CmEnv_clear_all(); if (idL == ID_INT) { @@ -4523,31 +4974,29 @@ int makeRule(Ast *ast) { CmEnv.idR = idR; - { - int generated_codesize = CompileIfSentenceFromAST(if_sentence, - code, code_offset); - if (generated_codesize < 0) { - return 0; - } - code_offset += generated_codesize; - } + if (!CompileIfSentenceFromAST(if_sentence)) return 0; + + // IMCode_Puts(0); + gencode_num += CmEnv_generate_VMcode(&code[2]); + #ifdef MYDEBUG - PutsCodeN(code, code_offset); exit(1); + PutsCodeN(code, gencode_num); exit(1); #endif - // PutsCodeN(code, code_offset); exit(1); + // PutsCodeN(code, gencode_num); exit(1); // printf("Rule: %s(id:%d) >< %s(id:%d).\n", // IdTable_get_name(idL), idL, // IdTable_get_name(idR), idR); - // PutsCodeN(&code[2], code_offset-2); + // PutsCodeN(&code[2], gencode_num-2); // exit(1); //ast_puts(ruleL); printf("><"); //ast_puts(ruleR); puts(""); + // Record the rule code for idR >< idL - RuleTable_record(idL, idR, code, code_offset); + RuleTable_record(idL, idR, code, gencode_num); if (idL != idR) { // Delete the rule code for idR >< idL @@ -4556,6 +5005,31 @@ int makeRule(Ast *ast) { } + + //#define DEBUG_PUT_RULE_CODE +#ifdef DEBUG_PUT_RULE_CODE + if (((strcmp(IdTable_get_name(idL), "Fib") == 0) && + (idR == ID_INT)) + || + ((strcmp(IdTable_get_name(idL), "fib") == 0) && + (idR == ID_INT)) + || + ((strcmp(IdTable_get_name(idL), "MergeCC") == 0) && + (idR == ID_CONS)) + ) { + + printf("Rule: %s >< %s.\n", + IdTable_get_name(idL), + IdTable_get_name(idR)); + + PutsCodeN(code, gencode_num+2); + // exit(1); + } +#endif + + + + return 1; } @@ -4652,8 +5126,10 @@ void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code) { &&E_LOOP, &&E_LOOP_RREC, &&E_LOOP_RREC1, &&E_LOOP_RREC2, &&E_LOADI, &&E_LOAD, &&E_LOADP, &&E_ADD, &&E_SUB, &&E_SUBI, &&E_MUL, &&E_DIV, &&E_MOD, - &&E_LT, &&E_LE, &&E_EQ, &&E_EQI, &&E_NE, - &&E_JMPEQ0, &&E_JMPCNCT_CONS, &&E_JMPCNCT, &&E_JMP, + &&E_LT, &&E_LE, &&E_EQ, &&E_EQI, &&E_NE, + &&E_LT_R0, &&E_LE_R0, &&E_EQ_R0, &&E_EQI_R0, &&E_NE_R0, + &&E_JMPEQ0, &&E_JMPEQ0_R0, &&E_JMP, &&E_JMPNEQ0, + &&E_JMPCNCT_CONS, &&E_JMPCNCT, &&E_UNM, &&E_RAND, &&E_CNCTGN, &&E_SUBSTGN, &&E_NOP, @@ -5177,6 +5653,69 @@ void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code) { pc +=4; goto *code[pc]; + + + E_LT_R0: + // puts("lt_r0 reg reg"); + if (FIX2INT(reg[(unsigned long)code[pc+1]]) < + FIX2INT(reg[(unsigned long)code[pc+2]])) { + reg[0] = INT2FIX(1); + } else { + reg[0] = INT2FIX(0); + } + pc +=3; + goto *code[pc]; + + E_LE_R0: + // puts("SUB reg reg"); + if (FIX2INT(reg[(unsigned long)code[pc+1]]) <= + FIX2INT(reg[(unsigned long)code[pc+2]])) { + reg[0] = INT2FIX(1); + } else { + reg[0] = INT2FIX(0); + } + pc +=3; + goto *code[pc]; + + E_EQ_R0: + // puts("SUB reg reg"); + if (reg[(unsigned long)code[pc+1]] == + reg[(unsigned long)code[pc+2]]) { + reg[0] = INT2FIX(1); + } else { + reg[0] = INT2FIX(0); + } + pc +=3; + goto *code[pc]; + + + E_EQI_R0: + // puts("SUB reg int"); + if (FIX2INT(reg[(unsigned long)code[pc+1]]) == + (unsigned long)code[pc+2]) { + reg[0] = INT2FIX(1); + } else { + reg[0] = INT2FIX(0); + } + + pc +=3; + goto *code[pc]; + + + + E_NE_R0: + // puts("SUB reg reg"); + if (reg[(unsigned long)code[pc+1]] != + reg[(unsigned long)code[pc+2]]) { + reg[0] = INT2FIX(1); + } else { + reg[0] = INT2FIX(0); + } + pc +=4; + goto *code[pc]; + + + E_JMPEQ0: // puts("JMPEQ0 reg pc"); // pc is a relative address, not absolute one! @@ -5187,6 +5726,25 @@ void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code) { goto *code[pc]; + E_JMPEQ0_R0: + // puts("JMPEQ0 pc"); + if (!FIX2INT(reg[0])) { + pc += (unsigned long)code[pc+1]; + } + pc +=2; + goto *code[pc]; + + + E_JMPNEQ0: + // puts("JMPNEQ0 reg pc"); + if (FIX2INT(reg[(unsigned long)code[pc+1]])) { + pc += (unsigned long)code[pc+2]; + } + pc +=3; + goto *code[pc]; + + + E_JMPCNCT_CONS: // puts("JMPCNCT_CONS reg pc"); #ifdef COUNT_CNCT @@ -5272,8 +5830,8 @@ void *ExecCode(int mode, VirtualMachine *restrict vm, void *restrict *code) { E_JMP: - // puts("JMP pc"); - pc += reg[(unsigned long)code[pc+1]]; + // puts("JMP pc"); + pc += (unsigned long)code[pc+1]; pc +=2; goto *code[pc]; @@ -6402,15 +6960,14 @@ int exec(Ast *at) { } - // Generate codes from CmEnv, where '0' means index of the `code', - // so here codes are stored from code[0]. - CmEnv_Retrieve_GNAME(); // IMCode_Puts(0); - CmEnv_Generate_VMCode(code, 0); + CmEnv_generate_VMcode(code); // PutsCode(code); exit(1); + + #ifdef COUNT_MKAGENT NumberOfMkAgent=0; #endif @@ -6494,24 +7051,30 @@ void *tpool_thread(void *arg) { vm = (VirtualMachine *)arg; + #ifdef CPU_ZERO cpu_set_t mask; CPU_ZERO(&mask); CPU_SET((vm->id)%CpuNum, &mask); if(sched_setaffinity(0, sizeof(mask), &mask)==-1) { - printf("WARNING:"); - printf("CPUNUM=%d, id=%d, cpuid=%d\n", CpuNum, vm->id, (vm->id)%CpuNum); + printf("WARNING:"); + printf("Thread%d works on Core%d/%d\n", vm->id, (vm->id)%CpuNum, CpuNum-1); } - //printf("CPUNUM=%d, id=%d, cpuid=%d\n", CpuNum, vm->id, (vm->id)%CpuNum); + // printf("Thread%d works on Core%d/%d\n", vm->id, (vm->id)%CpuNum, CpuNum-1); #endif + while (1) { VALUE t1, t2; while (!EQStack_Pop(vm, &t1, &t2)) { + + // Not sure, but it works well. Perhaps it can reduce race condition. + usleep(CAS_LOCK_USLEEP); + pthread_mutex_lock(&Sleep_lock); SleepingThreadsNum++; - + if (SleepingThreadsNum == MaxThreadsNum) { pthread_mutex_lock(&AllSleep_lock); pthread_cond_signal(&ActiveThread_all_sleep); @@ -6679,12 +7242,13 @@ int exec(Ast *at) { return 0; } - // '0' means that generated codes are stored in code[0,...]. CmEnv_Retrieve_GNAME(); - CmEnv_Generate_VMCode(code, 0); + // IMCode_Puts(0); exit(1); + + CmEnv_generate_VMcode(code); - // int codenum = CmEnv_Generate_VMCode(code, 0); - // PutsCodeN(code, codenum); exit(1); + // int codenum = CmEnv_generate_VMcode(code); + // PutsCodeN(code, codenum-2); //exit(1); ExecCode(1, VMs[0], code); @@ -6712,8 +7276,9 @@ int exec(Ast *at) { pthread_cond_broadcast(&EQStack_not_empty); pthread_mutex_unlock(&Sleep_lock); - //usleep(CAS_LOCK_USLEEP); // a little wait untill threads start. - usleep(10000); + // a little wait until all threads start. + //usleep(CAS_LOCK_USLEEP); + usleep(10000); // 0.01 sec wait // if some threads are working, wait for all of these to sleep. @@ -6768,286 +7333,290 @@ int yywrap() { int main(int argc, char *argv[]) { - int retrieve_flag = 1; // 1:エラー時にインタプリタへ復帰, 0:終了 + int i, param; + char *fname = NULL; + int max_EQStack=1<<8; // 512 + int retrieve_flag = 1; // 1: retrieve to interpreter even if error occurs +#ifndef EXPANDABLE_HEAP + // v0.5.6 + unsigned int heap_size=100000; +#endif + #ifdef MY_YYLINENO - InfoLineno_Init(); + InfoLineno_Init(); #endif // Pritty printing for local variables #ifdef PRETTY_VAR - Pretty_init(); + Pretty_init(); #endif - { - int i, param; - char *fname = NULL; - - int max_EQStack=1<<8; // 512 - - -#ifndef EXPANDABLE_HEAP - // v0.5.6 - unsigned int heap_size=100000; -#endif - + #ifndef THREAD - Init_WHNFinfo(); + Init_WHNFinfo(); #endif - ast_heapInit(); + ast_heapInit(); - for (i=1; i<argc; i++) { - if (*argv[i] == '-') { - switch (*(argv[i] +1)) { - case 'v': - printf("Inpla version %s\n", VERSION); - exit(-1); - break; - 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"); + for (i=1; i<argc; i++) { + if (*argv[i] == '-') { + switch (*(argv[i] +1)) { + case 'v': + printf("Inpla version %s\n", VERSION); + exit(-1); + break; + 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"); + #ifndef EXPANDABLE_HEAP - //v0.5.6 - printf(" -c <number> Set the size of heaps (Defalut: %8u)\n", - heap_size); + //v0.5.6 + printf(" -c <number> Set the size of heaps (Defalut: %8u)\n", heap_size); #endif - - printf(" -e <number> Set the unit size of the EQ stack (Default: %8u)\n", - max_EQStack); - + + printf(" -e <number> Set the unit size of the EQ stack (Default: %8u)\n", max_EQStack); + - // Special Options + // Special Options #ifdef THREAD - printf(" -t <number> Set the number of threads (Default: %8d)\n", - MaxThreadsNum); + printf(" -t <number> Set the number of threads (Default: %8d)\n", MaxThreadsNum); #else - printf(" -w Enable Weak Reduction strategy (Default: false)\n" - ); - - + printf(" -w Enable Weak Reduction strategy (Default: false)\n"); #endif - printf(" -d <Name>=<val> Bind <val> to <Name>\n" - ); - - printf(" -h Print this help message\n\n"); - exit(-1); - break; - - case 'd': - i++; - if (i < argc) { - char varname[100], val[100]; - char *tp; - tp = strtok(argv[i], "="); - snprintf(varname, sizeof(varname)-1, "%s", tp); - - if ((varname == NULL) - || (varname[0] < 'A') - || (varname[0] > 'Z')) { - puts("ERROR: 'id' in the format 'id=value' must start from a capital letter."); - exit(-1); - } + printf(" -d <Name>=<val> Bind <val> to <Name>\n"); + printf(" -h Print this help message\n\n"); + exit(-1); + break; + + + case 'd': + i++; + if (i < argc) { + char varname[100], val[100]; + char *tp; + tp = strtok(argv[i], "="); - tp = strtok(NULL, "="); - snprintf(val, sizeof(val)-1, "%s", tp); - if (val == NULL) { - puts("ERROR: 'value' in the format 'id=value' must an integer value."); - exit(-1); - } + // parsing for an identifier + snprintf(varname, sizeof(varname)-1, "%s", tp); + if ((varname == NULL) || (varname[0] < 'A') || (varname[0] > 'Z')) { + puts("ERROR: 'id' in the format 'id=value' must start from a capital letter."); + exit(-1); + } - int offset = 0; - if (val[0] == '-') { - offset = 1; - } - int valid = 1; - for (int idx = offset; idx < strlen(val); idx++) { - if ((val[idx] < '0') || (val[idx] > '9')) { - valid = 0; - break; - } - } + + tp = strtok(NULL, "="); - if (!valid) { - puts("ERROR: 'value' in the format 'id=value' must an integer value."); - exit(-1); - } + // parsing for a number + snprintf(val, sizeof(val)-1, "%s", tp); + if (val == NULL) { + puts("ERROR: 'value' in the format 'id=value' must an integer value."); + exit(-1); + } - ast_recordConst(varname, atoi(val)); + int offset = 0; + if (val[0] == '-') { + offset = 1; + } + int valid = 1; + for (int idx = offset; idx < strlen(val); idx++) { + if ((val[idx] < '0') || (val[idx] > '9')) { + valid = 0; + break; + } + } - - - } else { - puts("ERROR: The option switch '-d' needs a string such as VarName=value."); - exit(-1); + if (!valid) { + puts("ERROR: 'value' in the format 'id=value' must an integer value."); + exit(-1); } - break; - case 'f': - i++; - if (i < argc) { - fname = argv[i]; - retrieve_flag = 0; - } else { - printf("ERROR: The option switch '-f' needs a string of an input file name."); - exit(-1); - } - break; + ast_recordConst(varname, atoi(val)); + + } else { + puts("ERROR: The option switch '-d' needs a string such as VarName=value."); + exit(-1); + } + break; + + case 'f': + i++; + if (i < argc) { + fname = argv[i]; + retrieve_flag = 0; + } else { + printf("ERROR: The option switch '-f' needs a string of an input file name."); + exit(-1); + } + break; #ifndef EXPANDABLE_HEAP + case 'c': // v0.5.6 - case 'c': - i++; - if (i < argc) { - param = atoi(argv[i]); - if (param == 0) { - printf("ERROR: '%s' is illegal parameter for -c\n", argv[i]); - exit(-1); - } - } else { - printf("ERROR: The option switch '-c' needs a number as an argument."); - exit(-1); - } - heap_size=param; - break; + i++; + if (i < argc) { + param = atoi(argv[i]); + if (param == 0) { + printf("ERROR: '%s' is illegal parameter for -c\n", argv[i]); + exit(-1); + } + } else { + printf("ERROR: The option switch '-c' needs a number as an argument."); + exit(-1); + } + heap_size=param; + break; #endif - case 'e': - i++; - if (i < argc) { - param = atoi(argv[i]); - if (param == 0) { - printf("ERROR: '%s' is illegal parameter for -e\n", argv[i]); - exit(-1); - } - } else { - printf("ERROR: The option switch '-e' needs a natural number."); - exit(-1); - } - max_EQStack=param; - break; + case 'e': + i++; + if (i < argc) { + param = atoi(argv[i]); + if (param == 0) { + printf("ERROR: '%s' is illegal parameter for -e\n", argv[i]); + exit(-1); + } + } else { + printf("ERROR: The option switch '-e' needs a natural number."); + exit(-1); + } + max_EQStack=param; + break; #ifdef THREAD - case 't': - i++; - if (i < argc) { - param = atoi(argv[i]); - if (param == 0) { - printf("ERROR: '%s' is illegal parameter for -t\n", argv[i]); - exit(-1); - } - } else { - printf("ERROR: The option switch '-t' needs a number of threads."); - exit(-1); - } - - MaxThreadsNum=param; - break; + case 't': + i++; + if (i < argc) { + param = atoi(argv[i]); + if (param == 0) { + printf("ERROR: '%s' is illegal parameter for -t\n", argv[i]); + exit(-1); + } + } else { + printf("ERROR: The option switch '-t' needs a number of threads."); + exit(-1); + } + + MaxThreadsNum=param; + break; #else - case 'w': - WHNFinfo.enabled = 1; - break; + case 'w': + WHNFinfo.enabled = 1; + break; #endif - default: - printf("ERROR: Unrecognized option %s\n", argv[i]); - printf("Please use -h option for getting more information.\n\n"); - exit(-1); - } - } else { - printf("ERROR: Unrecognized option %s\n", argv[i]); - printf("Please use -h option for getting more information.\n\n"); - exit(-1); + default: + printf("ERROR: Unrecognized option %s\n", argv[i]); + printf("Use -h option for getting more information.\n\n"); + exit(-1); } + } else { + printf("ERROR: Unrecognized option %s\n", argv[i]); + printf("Use -h option for getting more information.\n\n"); + exit(-1); } + } - // Dealing with fname - if (fname == NULL) { - yyin = stdin; - - } else { - if (!(yyin = fopen(fname, "r"))) { - printf("Error: The file '%s' can not be opened.\n", fname); - exit(-1); - } + // Dealing with fname + if (fname == NULL) { + yyin = stdin; + + } else { + if (!(yyin = fopen(fname, "r"))) { + printf("Error: The file '%s' can not be opened.\n", fname); + exit(-1); } + } #ifndef THREAD - if (WHNFinfo.enabled) { - printf("Inpla %s (Weak Strategy) : Interaction nets as a programming language", - VERSION); - printf(" [%s]\n", BUILT_DATE); - } else { - printf("Inpla %s : Interaction nets as a programming language", - VERSION); - printf(" [built: %s]\n", BUILT_DATE); - } + if (WHNFinfo.enabled) { + printf("Inpla %s (Weak Strategy) : Interaction nets as a programming language", VERSION); + printf(" [%s]\n", BUILT_DATE); + } else { + printf("Inpla %s : Interaction nets as a programming language", VERSION); + printf(" [built: %s]\n", BUILT_DATE); + } #else - printf("Inpla %s : Interaction nets as a programming language", - VERSION); - printf(" [built: %s]\n", BUILT_DATE); + printf("Inpla %s : Interaction nets as a programming language", VERSION); + printf(" [built: %s]\n", BUILT_DATE); #endif #ifndef EXPANDABLE_HEAP - // v0.5.6 - heap_size = heap_size/MaxThreadsNum; + // v0.5.6 + heap_size = heap_size/MaxThreadsNum; #endif - IdTable_init(); - NameTable_init(); - RuleTable_init(); - + IdTable_init(); + NameTable_init(); + RuleTable_init(); + CodeAddr_init(); + #ifdef THREAD - GlobalEQStack_Init(MaxThreadsNum*8); + GlobalEQStack_Init(MaxThreadsNum*8); #endif + - CmEnv_Init(VM_LOCALVAR_SIZE); - #ifdef EXPANDABLE_HEAP #ifndef THREAD - VM_Init(&VM, max_EQStack); + VM_Init(&VM, max_EQStack); #else - tpool_init(max_EQStack); + tpool_init(max_EQStack); #endif + #else // ifndef EXPANDABLE_HEAP - //v0.5.6 + //v0.5.6 #ifndef THREAD - VM_Init(&VM, heap_size, max_EQStack); + VM_Init(&VM, heap_size, max_EQStack); #else - tpool_init(heap_size, max_EQStack); + tpool_init(heap_size, max_EQStack); #endif + #endif + + + + +#ifdef THREAD + // if some threads invoked by the initialise are still working, + // wait for all of these to sleep. + if (SleepingThreadsNum < MaxThreadsNum) { + pthread_mutex_lock(&AllSleep_lock); + pthread_cond_wait(&ActiveThread_all_sleep, &AllSleep_lock); + pthread_mutex_unlock(&AllSleep_lock); } - +#endif + + linenoiseHistoryLoad(".inpla.history.txt"); + // the main loop of parsing and execution while(1) { @@ -7055,26 +7624,26 @@ int main(int argc, char *argv[]) // When errors occur during parsing if (yyparse()!=0) { - + if (!retrieve_flag) { - exit(0); + exit(0); } - + if (yyin != stdin) { - fclose(yyin); - while (yyin!=stdin) { - popFP(); - } + fclose(yyin); + while (yyin!=stdin) { + popFP(); + } #ifdef MY_YYLINENO - InfoLineno_AllDestroy(); + InfoLineno_AllDestroy(); #endif } - + } } - + exit(0); } - + #include "lex.yy.c" @@ -89,8 +89,13 @@ char *Parse_closeStringBuffer() { <INITIAL>"=>" return (TO); <INITIAL>"~" return (CNCT); <INITIAL>"-" return (SUB); +<INITIAL>"&&" return(AND); +<INITIAL>"and" return(AND); +<INITIAL>"||" return(OR); +<INITIAL>"or" return(OR); +<INITIAL>"!" return(NOT); +<INITIAL>"not" return(NOT); <INITIAL>"|" return(PIPE); -<INITIAL>"&" return(AMP); <INITIAL>"=" return(LD); <INITIAL>"==" return(EQUAL); <INITIAL>"!=" return(NE); |
