iris

small scheme interpreter
git clone git://git.2f30.org/iris
Log | Files | Refs | LICENSE

commit 8c1168fc1c6d93116ce70843e8e2f06e34ec18d5
parent 1f730e0a33a4821070b539c6ccfecbbbd47eb18f
Author: sin <sin@2f30.org>
Date:   Fri, 16 May 2014 13:16:42 +0100

Add integer type predicate

Diffstat:
Mdebug.c | 4++--
Mlexer.c | 20++++++++++----------
Mlexer.h | 2+-
Mparser.c | 58++++++++++++++++++++++++++++++++++++++++------------------
4 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/debug.c b/debug.c @@ -25,8 +25,8 @@ printtok(struct tok *t) case TBoolean: printf("token: boolean, value: '%s'", l); break; - case TNumber: - printf("token number, value: '%s'", l); + case TInteger: + printf("token integer, value: '%s'", l); break; case TCharacter: printf("token character, value: '%s'", l); diff --git a/lexer.c b/lexer.c @@ -12,8 +12,8 @@ enum state { SIdentifier, SProbable_Boolean, SBoolean, - SNumber, - SSigned_Number, + SInteger, + SSigned_Integer, SProbable_Character, SCharacter, SProbable_String, @@ -65,9 +65,9 @@ again: else if (*e == '#') state = SProbable_Boolean; else if (isdigit(*e) != 0) - state = SNumber; + state = SInteger; else if (*e == '-' || *e == '+') - state = SSigned_Number; + state = SSigned_Integer; else if (*e == '"') state = SProbable_String; else if (*e == '(') @@ -122,9 +122,9 @@ again: tok.s = "missing delimiter after boolean"; tok.e = NULL; return tok; - case SNumber: + case SInteger: if (delim(*e) != 0) { - tok.type = TNumber; + tok.type = TInteger; tok.s = s; tok.e = e; ungetc(*e, in); @@ -132,19 +132,19 @@ again: } if (isdigit(*e) == 0) { tok.type = TError; - tok.s = "not a number"; + tok.s = "not a integer"; tok.e = NULL; return tok; } break; - case SSigned_Number: + case SSigned_Integer: if (isdigit(*e) == 0) { tok.type = TError; - tok.s = "not a number"; + tok.s = "not a integer"; tok.e = NULL; return tok; } - state = SNumber; + state = SInteger; break; case SProbable_Character: if (isalpha(*e) != 0) { diff --git a/lexer.h b/lexer.h @@ -4,7 +4,7 @@ enum toktype { TEof = -1, TIdentifier, TBoolean, - TNumber, + TInteger, TCharacter, TString, TLparen, diff --git a/parser.c b/parser.c @@ -13,7 +13,7 @@ enum objtype { OEof = -1, OIdentifier, OBoolean, - ONumber, + OInteger, OCharacter, OString, OEmptylist, @@ -40,7 +40,7 @@ struct object { struct { bool v; } b; - /* number */ + /* integer */ struct { long v; } n; @@ -75,6 +75,7 @@ static struct object *evalset(struct object *); /* primitive procedures */ static struct object *evalboolean(struct object *); static struct object *evaldiff(struct object *); +static struct object *evalinteger(struct object *); static struct object *evalnull(struct object *); static struct object *evalplus(struct object *); @@ -96,9 +97,10 @@ struct { struct object *(*fn)(struct object *); } procs[] = { { .name = "boolean", .fn = evalboolean }, - { .name = "diff", .fn = evaldiff }, - { .name = "null", .fn = evalnull }, - { .name = "plus", .fn = evalplus }, + { .name = "diff", .fn = evaldiff }, + { .name = "integer", .fn = evalinteger }, + { .name = "null", .fn = evalnull }, + { .name = "plus", .fn = evalplus }, }; static struct object * @@ -152,12 +154,12 @@ boolean(bool v) } static struct object * -number(long v) +integer(long v) { struct object *o; o = newobject(); - o->type = ONumber; + o->type = OInteger; o->d.n.v = v; return o; } @@ -260,8 +262,8 @@ sexpression(FILE *in) case TBoolean: /* #t or #f */ return boolean(l[1] == 't' ? true : false); - case TNumber: - return number(strtol(l, 0, 10)); + case TInteger: + return integer(strtol(l, 0, 10)); case TCharacter: /* #\c */ return character(l[2]); @@ -438,8 +440,8 @@ dodiff(struct object *o, struct object *n) otmp = eval(car(o)); if (otmp->type == OError) return otmp; - if (otmp->type != ONumber) - return error("expected number"); + if (otmp->type != OInteger) + return error("expected integer"); n->d.n.v -= otmp->d.n.v; return dodiff(cdr(o), n); } @@ -457,8 +459,8 @@ evaldiff(struct object *o) n = eval(cadr(o)); if (n->type == OError) return n; - if (n->type != ONumber) - return error("expected number"); + if (n->type != OInteger) + return error("expected integer"); if (!caddr(o)) { n->d.n.v *= -1; return n; @@ -467,6 +469,26 @@ evaldiff(struct object *o) } static struct object * +evalinteger(struct object *o) +{ + struct object *arg; + + if (o->type != OPair) + return NULL; + if (car(o)->type != OIdentifier || + strcmp(car(o)->d.i.s, "integer") != 0) + return NULL; + arg = eval(cadr(o)); + if (arg->type == OError) + return arg; + if (caddr(o)) + return error("multiple arguments"); + if (arg->type == OInteger) + return boolean(true); + return boolean(false); +} + +static struct object * evalnull(struct object *o) { struct object *arg; @@ -496,8 +518,8 @@ doplus(struct object *o, struct object *n) otmp = eval(car(o)); if (otmp->type == OError) return otmp; - if (otmp->type != ONumber) - return error("expected number"); + if (otmp->type != OInteger) + return error("expected integer"); n->d.n.v += otmp->d.n.v; return doplus(cdr(o), n); } @@ -510,7 +532,7 @@ evalplus(struct object *o) if (car(o)->type != OIdentifier || strcmp(car(o)->d.i.s, "plus") != 0) return NULL; - return doplus(cdr(o), number(0)); + return doplus(cdr(o), integer(0)); } struct object * @@ -524,7 +546,7 @@ eval(struct object *o) case OError: case OEof: case OBoolean: - case ONumber: + case OInteger: case OCharacter: case OString: return o; @@ -586,7 +608,7 @@ print(struct object *o) case OBoolean: printf("#%c", o->d.b.v == false ? 'f' : 't'); break; - case ONumber: + case OInteger: printf("%ld", o->d.n.v); break; case OCharacter: