summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h13
-rw-r--r--eval.c67
-rw-r--r--lexer.c61
-rw-r--r--main.c15
4 files changed, 88 insertions, 68 deletions
diff --git a/apl9.h b/apl9.h
index 620eae6..f6c963c 100644
--- a/apl9.h
+++ b/apl9.h
@@ -29,7 +29,7 @@ typedef enum
/* Data types */
typedef struct Array Array;
-typedef struct Expr Expr;
+typedef struct Statement Statement;
typedef struct Function Function;
typedef struct Datum Datum;
typedef struct Symbol Symbol;
@@ -49,17 +49,18 @@ struct Array
};
};
-struct Expr
+struct Statement
{
int ntoks;
Datum *toks;
+ Statement *next;
};
struct Function
{
union {
int code;
- Expr *dfn;
+ Statement *dfn;
};
Array *left;
};
@@ -69,7 +70,7 @@ struct Datum
datumTag tag;
union {
Array *array;
- Expr expr;
+ Statement stmt;
Function func;
Symbol *symbol;
};
@@ -98,7 +99,7 @@ Rune *ppdatums(Datum *, int);
Rune *pparray(Array *);
/* lexer.c */
-Datum *lexline(Rune *, int *, Symtab *);
+Statement *lexline(Rune *, Symtab *);
/* array.c */
Array *mkarray(int, int, int);
@@ -108,7 +109,7 @@ int simplearray(Array *);
int simplescalar(Array *);
/* eval.c */
-Datum *eval(Datum *, int *);
+Datum *eval(Statement *);
/* symbol.c */
Symbol *getsym(Symtab *, Rune *);
diff --git a/eval.c b/eval.c
index f6cdb0d..11809a8 100644
--- a/eval.c
+++ b/eval.c
@@ -59,47 +59,46 @@ evalfn evalfns[15][15] = {
};
Datum *
-eval(Datum *tokens, int *ntoks)
+eval(Statement *stmt)
{
errormsg = nil;
/* start by looking up first variable if needed */
- if(*ntoks > 0 && tokens[(*ntoks)-1].tag == NameTag){
- Datum *value = lookup(tokens[(*ntoks)-1]);
+ if(stmt->ntoks > 0 && stmt->toks[stmt->ntoks-1].tag == NameTag){
+ Datum *value = lookup(stmt->toks[stmt->ntoks-1]);
if(value == nil)
- *ntoks = 0;
+ return nil;
else
- tokens[(*ntoks)-1] = *value;
+ stmt->toks[stmt->ntoks-1] = *value;
}
- while(*ntoks > 1){
+ while(stmt->ntoks > 1){
int maxlevel = 0;
int offset;
evalfn fn = nil;
- traceprint("CURRENT: %S\n", ppdatums(tokens, *ntoks));
- for(offset = (*ntoks)-1; offset >= 0; offset--){
+ traceprint("CURRENT: %S\n", ppdatums(stmt->toks, stmt->ntoks));
+ for(offset = stmt->ntoks-1; offset >= 0; offset--){
int level;
retry:
if(offset == 0)
level = 0;
else{
- Datum left = tokens[offset-1];
- Datum right = tokens[offset];
+ Datum left = stmt->toks[offset-1];
+ Datum right = stmt->toks[offset];
level = bindingstrengths[left.tag][right.tag];
}
- if(level == 0 && tokens[offset-1].tag == NameTag){
- Datum *value = lookup(tokens[offset-1]);
- if(value == nil){
- *ntoks = 0;
- return tokens;
- }else{
- tokens[offset-1] = *value;
+ if(level == 0 && stmt->toks[offset-1].tag == NameTag){
+ Datum *value = lookup(stmt->toks[offset-1]);
+ if(value == nil)
+ return nil;
+ else{
+ stmt->toks[offset-1] = *value;
goto retry;
}
}else if(level < maxlevel){
- Datum left = tokens[offset];
- Datum right = tokens[offset+1];
+ Datum left = stmt->toks[offset];
+ Datum right = stmt->toks[offset+1];
fn = evalfns[left.tag][right.tag];
traceprint("Reducing %S and %S (fn=%p, level=%d, max=%d)\n", ppdatum(left), ppdatum(right), fn, level, maxlevel);
break;
@@ -108,15 +107,21 @@ retry:
}
if(maxlevel == 0){
errormsg = L"No reduce rule. Syntax error.";
- *ntoks = 0;
+ return nil;
}else{
- tokens[offset] = fn(tokens[offset],tokens[offset+1]);
- for(int i = offset+1; i < (*ntoks)-1; i++)
- tokens[i] = tokens[i+1];
- (*ntoks)--;
+ stmt->toks[offset] = fn(stmt->toks[offset],stmt->toks[offset+1]);
+ for(int i = offset+1; i < stmt->ntoks-1; i++)
+ stmt->toks[i] = stmt->toks[i+1];
+ stmt->ntoks--;
}
}
- return tokens;
+ if(stmt->ntoks == 1){
+ if(stmt->next)
+ return eval(stmt->next);
+ else
+ return stmt->toks;
+ }else
+ return nil;
}
Datum *
@@ -173,10 +178,10 @@ Datum
lpar(Datum left, Datum right)
{
/* build up a parthenthesised expression */
- left.expr.ntoks++;
- left.expr.toks = realloc(left.expr.toks, sizeof(Datum) * left.expr.ntoks);
- left.expr.toks[left.expr.ntoks-1] = right;
- traceprint("LPAR: %S\n", ppdatums(left.expr.toks, left.expr.ntoks));
+ left.stmt.ntoks++;
+ left.stmt.toks = realloc(left.stmt.toks, sizeof(Datum) * left.stmt.ntoks);
+ left.stmt.toks[left.stmt.ntoks-1] = right;
+ traceprint("LPAR: %S\n", ppdatums(left.stmt.toks, left.stmt.ntoks));
return left;
}
@@ -185,8 +190,8 @@ rpar(Datum left, Datum right)
{
/* evaluate a parenthesis expression and return the result */
USED(right);
- traceprint("RPAR: %S\n", ppdatums(left.expr.toks, left.expr.ntoks));
- Datum *result = eval(left.expr.toks, &left.expr.ntoks);
+ traceprint("RPAR: %S\n", ppdatums(left.stmt.toks, left.stmt.ntoks));
+ Datum *result = eval(&left.stmt);
result[0].array->stranded = 0;
return result[0]; /* TODO handle error if ntoks != 1 */
}
diff --git a/lexer.c b/lexer.c
index a7557c2..d269e11 100644
--- a/lexer.c
+++ b/lexer.c
@@ -8,40 +8,46 @@ Rune primmonopnames[] = L"¨⍨⌸⌶&";
Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺";
Rune primhybridnames[] = L"/\⌿⍀";
-Datum *
-lexline(Rune *line, int *ntoks, Symtab *symtab)
+Statement *
+lexline(Rune *line, Symtab *symtab)
{
int offset = 0;
int len = runestrlen(line);
- Datum *tokens = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1);
- *ntoks = 0;
+ Statement *stmt = malloc(sizeof(Statement));
+ stmt->ntoks = 0;
+ stmt->toks = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1);
+ stmt->next = nil;
+
while(offset < len){
Rune *p;
if(isspacerune(line[offset])){
offset++;
continue;
- }else if(runestrchr(L"(){}[]←", line[offset])){
+ }else if(runestrchr(L"(){}[]←⋄", line[offset])){
switch(line[offset]){
- case '(': tokens[*ntoks].tag = LParTag; break;
- case ')': tokens[*ntoks].tag = RParTag; break;
- case '{': tokens[*ntoks].tag = LCurlTag; break;
- case '}': tokens[*ntoks].tag = RCurlTag; break;
- case '[': tokens[*ntoks].tag = LBracketTag; break;
- case ']': tokens[*ntoks].tag = RBracketTag; break;
- case L'←': tokens[*ntoks].tag = ArrowTag; break;
+ case '(': stmt->toks[stmt->ntoks].tag = LParTag; break;
+ case ')': stmt->toks[stmt->ntoks].tag = RParTag; break;
+ case '{': stmt->toks[stmt->ntoks].tag = LCurlTag; break;
+ case '}': stmt->toks[stmt->ntoks].tag = RCurlTag; break;
+ case '[': stmt->toks[stmt->ntoks].tag = LBracketTag; break;
+ case ']': stmt->toks[stmt->ntoks].tag = RBracketTag; break;
+ case L'←': stmt->toks[stmt->ntoks].tag = ArrowTag; break;
+ case L'⋄':
+ stmt->next = lexline(&line[offset+1], symtab);
+ goto end;
}
offset++;
}else if(p = runestrchr(primfuncnames, line[offset])){
- tokens[*ntoks].tag = FunctionTag;
- tokens[*ntoks].func.code = p-primfuncnames;
+ stmt->toks[stmt->ntoks].tag = FunctionTag;
+ stmt->toks[stmt->ntoks].func.code = p-primfuncnames;
offset++;
}else if(p = runestrchr(primmonopnames, line[offset])){
- tokens[*ntoks].tag = MonadicOpTag;
- tokens[*ntoks].func.code = p-primmonopnames;
+ stmt->toks[stmt->ntoks].tag = MonadicOpTag;
+ stmt->toks[stmt->ntoks].func.code = p-primmonopnames;
offset++;
}else if(p = runestrchr(primdyadopnames, line[offset])){
- tokens[*ntoks].tag = DyadicOpTag;
- tokens[*ntoks].func.code = p-primdyadopnames;
+ stmt->toks[stmt->ntoks].tag = DyadicOpTag;
+ stmt->toks[stmt->ntoks].func.code = p-primdyadopnames;
offset++;
}else if(isdigitrune(line[offset])){
char buf[64];
@@ -51,8 +57,8 @@ lexline(Rune *line, int *ntoks, Symtab *symtab)
offset++;
}
*p = 0;
- tokens[*ntoks].tag = ArrayTag;
- tokens[*ntoks].array = mkscalarint(atoll(buf));
+ stmt->toks[stmt->ntoks].tag = ArrayTag;
+ stmt->toks[stmt->ntoks].array = mkscalarint(atoll(buf));
}else if(isalpharune(line[offset]) || line[offset] == L'⎕'){
int quadname = L'⎕' == line[offset];
Rune buf[64];
@@ -66,14 +72,17 @@ lexline(Rune *line, int *ntoks, Symtab *symtab)
offset++;
}
*p = 0;
- tokens[*ntoks].tag = NameTag;
- tokens[*ntoks].symbol = getsym(symtab, buf);
+ stmt->toks[stmt->ntoks].tag = NameTag;
+ stmt->toks[stmt->ntoks].symbol = getsym(symtab, buf);
}else{
print("Can't lex: %S\n", &line[offset]);
- *ntoks = 0;
- break;
+ free(stmt->toks);
+ free(stmt);
+ return 0;
}
- (*ntoks)++;
+ stmt->ntoks++;
}
- return tokens;
+end:
+ stmt->toks = realloc(stmt->toks, sizeof(Datum) * stmt->ntoks);
+ return stmt;
} \ No newline at end of file
diff --git a/main.c b/main.c
index 378f840..784bc25 100644
--- a/main.c
+++ b/main.c
@@ -58,13 +58,18 @@ prompt(Rune *pr)
Datum *
evalline(Rune *line)
{
- int ntoks;
- Datum *tokens = lexline(line, &ntoks, globalsymtab);
- Datum *result = eval(tokens, &ntoks);
- if(ntoks == 1)
+ Statement *stmts = lexline(line, globalsymtab);
+ Datum *result = eval(stmts);
+ if(result)
return result;
else{
- free(tokens);
+ Statement *s = stmts;
+ while(s != nil){
+ Statement *tmp = s;
+ s = s->next;
+ free(tmp->toks);
+ free(tmp);
+ }
return nil;
}
} \ No newline at end of file