From ea4ac7241e6ec032fc96f943ce76d43f32580a75 Mon Sep 17 00:00:00 2001 From: mtardy Date: Thu, 3 Sep 2020 13:04:10 +0200 Subject: [PATCH] Add floating point numbers --- object.c | 65 ++++++++++++++++------- parse.leg | 154 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 146 insertions(+), 73 deletions(-) diff --git a/object.c b/object.c index d59348f..c5f6488 100644 --- a/object.c +++ b/object.c @@ -11,9 +11,11 @@ # include #endif -typedef long long int_t; +typedef long long int_t; +typedef long double flt_t; #define FMT_I "%lli" +#define FMT_F "%Lg" void *memcheck(void *ptr) { @@ -71,6 +73,7 @@ char *xstrdup(char *s) typedef enum { Undefined, Integer, + Float, String, Symbol, Function, @@ -91,6 +94,11 @@ struct Integer { int_t _value; }; +struct Float { + type_t type; + flt_t _value; +}; + struct String { type_t type; char *value; @@ -142,6 +150,7 @@ union object { type_t type; struct Undefined Undefined; struct Integer Integer; + struct Float Float; struct String String; struct Symbol Symbol; struct Function Function; @@ -170,7 +179,7 @@ int isInteger(oop obj) } #if (USE_TAG) -# define getType(PTR) (((intptr_t)(PTR) & 1) ? Integer : (PTR)->type) +# define getType(PTR) (type_t)(((intptr_t)(PTR) & 1) ? Integer : (PTR)->type) #else type_t getType(oop ptr) { @@ -211,7 +220,7 @@ int_t getInteger(oop obj) if (isTag(obj)) return (intptr_t)obj >> 1; #endif if (!isInteger(obj)) { - fprintf(stderr, "\nNon-integer in arithmetic expression\n"); + fprintf(stderr, "\ngetInteger call on non-integer\n"); exit(1); } return get(obj, Integer, _value); @@ -236,6 +245,14 @@ oop makeInteger(int_t value) return newInt; } +oop makeFloat(flt_t value) +{ + oop newFloat= malloc(sizeof(struct Float)); + newFloat->type= Float; + newFloat->Float._value= value; + return newFloat; +} + oop makeString(char *value) { oop newString = malloc(sizeof(struct String)); @@ -328,20 +345,26 @@ int oopcmp(oop a, oop b) type_t ta = getType(a), tb = getType(b); if (ta == tb) { switch (getType(a)) { - case Integer: { - int l= getInteger(a), r= getInteger(b); - if (l < r) return -1; - if (l > r) return 1; - return 0; - } - case String: - return strcmp(get(a, String, value), get(b, String, value)); - default: { - intptr_t l= (intptr_t)a, r= (intptr_t)b; - if (l < r) return -1; - if (l > r) return 1; - return 0; - } + case Integer: { + int_t l= getInteger(a), r= getInteger(b); + if (l < r) return -1; + if (l > r) return 1; + return 0; + } + case Float: { + flt_t l= get(a, Float, _value), r= get(b, Float, _value); + if (l < r) return -1; + if (l > r) return 1; + return 0; + } + case String: + return strcmp(get(a, String, value), get(b, String, value)); + default: { + intptr_t l= (intptr_t)a, r= (intptr_t)b; + if (l < r) return -1; + if (l > r) return 1; + return 0; + } } } return ta - tb; @@ -573,11 +596,17 @@ void printOn(StringBuffer *buf, oop obj, int indent) return; } case Integer: { - char tmp[40]; + char tmp[44]; int length = snprintf(tmp, sizeof(tmp), FMT_I, getInteger(obj)); StringBuffer_appendAll(buf, tmp, length); return; } + case Float: { + char tmp[44]; + int length = snprintf(tmp, sizeof(tmp), FMT_F, get(obj, Float, _value)); + StringBuffer_appendAll(buf, tmp, length); + return; + } case String: { StringBuffer_appendAll(buf, get(obj, String, value), string_size(obj)); return; diff --git a/parse.leg b/parse.leg index 668cb08..7a470f8 100644 --- a/parse.leg +++ b/parse.leg @@ -7,11 +7,12 @@ */ #include +#include #define DO_PROTOS() \ _DO(If) _DO(While) _DO(Do) _DO(For) _DO(ForIn) _DO(Switch) _DO(Call) \ _DO(Invoke) _DO(Func) _DO(Block) _DO(Declaration) _DO(Assign) \ - _DO(Map) _DO(Symbol) _DO(Integer) _DO(String) \ + _DO(Map) _DO(Symbol) _DO(Integer) _DO(Float) _DO(String) \ _DO(Logor) _DO(Logand) _DO(Bitor) _DO(Bitxor) _DO(Bitand) \ _DO(Equal) _DO(Noteq) _DO(Less) _DO(Lesseq) _DO(Greater) _DO(Greatereq) _DO(Shleft) _DO(Shright) \ _DO(Add) _DO(Sub) _DO(Mul) _DO(Div) _DO(Mod) _DO(Not) _DO(Neg) _DO(Com) \ @@ -296,6 +297,13 @@ oop newInteger(oop value) return integer; } +oop newFloat(oop value) +{ + oop obj = newObject(Float_proto); + map_set(obj, value_symbol, value); + return obj; +} + int digitValue(int c) { if (c < '0') return -1; @@ -725,7 +733,7 @@ prod = l:prefix )* { $$ = l } prefix = PLUS n:prefix { $$= n } - | MINUS n:prefix { $$= newUnary(Neg_proto, n) } + | NEGATE n:prefix { $$= newUnary(Neg_proto, n) } | TILDE n:prefix { $$= newUnary(Com_proto, n) } | PLING n:prefix { $$= newUnary(Not_proto, n) } | PLUSPLUS n:prefix { $$= newPreIncrement(n) } @@ -756,7 +764,8 @@ argumentList = LPAREN m:makeMap ) ? RPAREN { $$ = m } -value = n:NUMBER { $$ = newInteger(n) } +value = n:FLOAT { $$ = newFloat(n) } + | n:INTEGER { $$ = newInteger(n) } | s:string { $$ = newString(s) } | s:symbol { $$ = s } | m:map { $$ = newMap(m) } @@ -789,7 +798,7 @@ map = LCB m:makeMap makeMap = { $$ = makeMap() } -key = IDENT | NUMBER +key = IDENT | INTEGER - = (blank | comment)* @@ -807,11 +816,15 @@ keyword = FUN | SYNTAX | VAR | SWITCH | CASE | DEFAULT | DO | FOR | IN | WHILE | IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } -NUMBER = '0b' < [01]+ > - { $$ = makeInteger(strtol(yytext, 0, 2)) } - | '0x' < [0-9a-fA-F]+ > - { $$ = makeInteger(strtol(yytext, 0, 16)) } - | '0' < [0-7]+ > - { $$ = makeInteger(strtol(yytext, 0, 8)) } - | < [0-9]+ > - { $$ = makeInteger(strtol(yytext, 0, 10)) } - | SQUOTE < (!SQUOTE char) > SQUOTE - { $$ = makeInteger(unescape(yytext)[0]) } +INTEGER = '0b' < [01]+ > - { $$ = makeInteger(strtol(yytext, 0, 2)) } + | '0x' < [0-9a-fA-F]+ > - { $$ = makeInteger(strtol(yytext, 0, 16)) } + | '0' < [0-7]+ > - { $$ = makeInteger(strtol(yytext, 0, 8)) } + | < [0-9]+ > - { $$ = makeInteger(strtol(yytext, 0, 10)) } + | SQUOTE < (!SQUOTE char) > SQUOTE - { $$ = makeInteger(unescape(yytext)[0]) } + +FLOAT = < [-+]* [0-9]+ '.' [0-9]* ('e'[-+]*[0-9]+)? > - { $$ = makeFloat(strtold(yytext, 0)) } + | < [-+]* [0-9]* '.' [0-9]+ ('e'[-+]*[0-9]+)? > - { $$ = makeFloat(strtold(yytext, 0)) } + | < [-+]* [0-9]+ ('e'[-+]*[0-9]+) > - { $$ = makeFloat(strtold(yytext, 0)) } FUN = 'fun' ![a-zA-Z0-9_] - SYNTAX = 'syntax' ![a-zA-Z0-9_] - @@ -850,6 +863,7 @@ SHLEFT = '<<' ![=] - SHRIGHT = '>>' ![=] - PLUS = '+' ![+=] - MINUS = '-' ![-=] - +NEGATE = '-' ![-=0-9.] - PLUSPLUS = '++' - MINUSMINUS = '--' - TILDE = '~' - @@ -908,6 +922,7 @@ oop clone(oop obj) switch(getType(obj)) { case Undefined: case Integer: + case Float: case Function: case Symbol: return obj; @@ -1005,37 +1020,67 @@ void runtimeError(char *fmt, ...) #define TYPESIG(L, R) L*NTYPES+R #define CASE(L, R) case TYPESIG(L, R) -oop addOperation(oop ast, oop lhs, oop rhs) +oop addOperation(oop lhs, oop rhs) { switch (TYPESIG(getType(lhs), getType(rhs))) { - CASE(Integer, Integer): { - return makeInteger(getInteger(lhs) + getInteger(rhs)); - } - CASE(String, String): { - return string_concat(lhs, rhs); - } + CASE(Integer, Integer): return makeInteger(getInteger(lhs) + getInteger(rhs)); + CASE(Integer, Float ): return makeFloat(getInteger(lhs) + get(rhs, Float, _value)); + CASE(Float , Integer): return makeFloat(get(lhs, Float, _value) + getInteger(rhs)); + CASE(Float , Float ): return makeFloat(get(lhs, Float, _value) + get(rhs, Float, _value)); + CASE(String , String ): return string_concat(lhs, rhs); } runtimeError("addition between two incompatible types"); return NULL; // to prevent: control may reach end of non-void function } -oop mulOperation(oop ast, oop lhs, oop rhs) +oop subOperation(oop lhs, oop rhs) { switch (TYPESIG(getType(lhs), getType(rhs))) { - CASE(Integer, Integer): { - return makeInteger(getInteger(lhs) * getInteger(rhs)); - } - CASE(String, Integer): { - return string_mul(lhs, rhs); - } - CASE(Integer, String): { - return string_mul(rhs, lhs); - } + CASE(Integer, Integer): return makeInteger(getInteger(lhs) - getInteger(rhs)); + CASE(Integer, Float ): return makeFloat(getInteger(lhs) - get(rhs, Float, _value)); + CASE(Float , Integer): return makeFloat(get(lhs, Float, _value) - getInteger(rhs)); + CASE(Float , Float ): return makeFloat(get(lhs, Float, _value) - get(rhs, Float, _value)); + } + runtimeError("substraction between two incompatible types"); + return NULL; // to prevent: control may reach end of non-void function +} + +oop mulOperation(oop lhs, oop rhs) +{ + switch (TYPESIG(getType(lhs), getType(rhs))) { + CASE(Integer, Integer): return makeInteger(getInteger(lhs) * getInteger(rhs)); + CASE(Integer, Float ): return makeFloat(getInteger(lhs) * get(rhs, Float, _value)); + CASE(Float , Integer): return makeFloat(get(lhs, Float, _value) * getInteger(rhs)); + CASE(Float , Float ): return makeFloat(get(lhs, Float, _value) * get(rhs, Float, _value)); + CASE(String , Integer): return string_mul(lhs, rhs); + CASE(Integer, String ): return string_mul(rhs, lhs); } runtimeError("multiplication between two incompatible types"); return NULL; // to prevent: control may reach end of non-void function } +oop divOperation(oop lhs, oop rhs) +{ + switch (TYPESIG(getType(lhs), getType(rhs))) { + CASE(Integer, Integer): return makeInteger(getInteger(lhs) / getInteger(rhs)); + CASE(Integer, Float ): return makeFloat(getInteger(lhs) / get(rhs, Float, _value)); + CASE(Float , Integer): return makeFloat(get(lhs, Float, _value) / getInteger(rhs)); + CASE(Float , Float ): return makeFloat(get(lhs, Float, _value) / get(rhs, Float, _value)); + } + runtimeError("division between two incompatible types"); + return NULL; // to prevent: control may reach end of non-void function +} + +oop modOperation(oop lhs, oop rhs) +{ + switch (TYPESIG(getType(lhs), getType(rhs))) { + CASE(Integer, Integer): return makeInteger(getInteger(lhs) % getInteger(rhs)); + CASE(Float , Float ): return makeFloat(fmodl(get(lhs, Float, _value), get(rhs, Float, _value))); + } + runtimeError("modulo between two incompatible types"); + return NULL; // to prevent: control may reach end of non-void function +} + #undef TYPESIG #undef CASE @@ -1061,11 +1106,11 @@ oop applyOperator(oop ast, oop op, oop lhs, oop rhs) { if (null != op) { assert(is(Symbol, op)); switch (get(op, Symbol, prototype)) { - case t_Add: return addOperation(ast, lhs, rhs); - case t_Sub: return makeInteger(getInteger(lhs) - getInteger(rhs)); - case t_Mul: return mulOperation(ast, lhs, rhs); - case t_Div: return makeInteger(getInteger(lhs) / getInteger(rhs)); - case t_Mod: return makeInteger(getInteger(lhs) % getInteger(rhs)); + case t_Add: return addOperation(lhs, rhs); + case t_Sub: return subOperation(lhs, rhs); + case t_Mul: return mulOperation(lhs, rhs); + case t_Div: return divOperation(lhs, rhs); + case t_Mod: return modOperation(lhs, rhs); case t_Bitor: return makeInteger(getInteger(lhs) | getInteger(rhs)); case t_Bitxor: return makeInteger(getInteger(lhs) ^ getInteger(rhs)); case t_Bitand: return makeInteger(getInteger(lhs) & getInteger(rhs)); @@ -1170,15 +1215,16 @@ oop eval(oop scope, oop ast) } switch(getType(ast)) { - case Undefined: - case Integer: - case String: - case Function: - return ast; - case Symbol: - return getVariable(scope, ast); - case Map: - break; + case Undefined: + case Integer: + case Float: + case String: + case Function: + return ast; + case Symbol: + return getVariable(scope, ast); + case Map: + break; } assert(is(Map, ast)); @@ -1591,6 +1637,7 @@ oop eval(oop scope, oop ast) } case t_Symbol: case t_Integer: + case t_Float: case t_String: { return map_get(ast, value_symbol); } @@ -1620,6 +1667,12 @@ oop eval(oop scope, oop ast) oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ } +# define BINARYOP(NAME, FUNCPREFIX) \ + case t_##NAME: { \ + oop lhs = eval(scope, map_get(ast, lhs_symbol)); \ + oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ + return FUNCPREFIX##Operation(lhs, rhs); \ + } BINARY(Bitor, | ); BINARY(Bitxor, ^ ); BINARY(Bitand, & ); @@ -1631,21 +1684,12 @@ oop eval(oop scope, oop ast) RELATION(Greater, > ); BINARY(Shleft, <<); BINARY(Shright, >>); -// BINARY(Add, + ); - case t_Add: { - oop lhs = eval(scope, map_get(ast, lhs_symbol)); - oop rhs = eval(scope, map_get(ast, rhs_symbol)); - return addOperation(ast, lhs, rhs); - } - BINARY(Sub, - ); -// BINARY(Mul, * ); - case t_Mul: { - oop lhs = eval(scope, map_get(ast, lhs_symbol)); - oop rhs = eval(scope, map_get(ast, rhs_symbol)); - return mulOperation(ast, lhs, rhs); - } - BINARY(Div, / ); - BINARY(Mod, % ); + BINARYOP(Add, add); + BINARYOP(Mul, mul); + BINARYOP(Sub, sub); + BINARYOP(Div, div); + BINARYOP(Mod, mod); +# undef BINARYOP # undef BINARY # undef RELATION case t_Not: {