From 62ba271c458b9fb1d6a99b42d961420b750fa6b1 Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sat, 6 Apr 2024 14:40:50 +0100 Subject: [PATCH 1/7] rationals compare --- docs/ArithmeticTypes.drawio | 31 +++++++++++ fn/googol.fn | 1 + fn/irrational.fn | 1 + fn/rational.fn | 15 +++--- src/arithmetic.c | 101 ++++++++++++++++++++++++++---------- src/arithmetic.h | 17 +++--- src/step.c | 46 ++++++++-------- src/value.h | 6 +++ 8 files changed, 153 insertions(+), 65 deletions(-) create mode 100644 docs/ArithmeticTypes.drawio create mode 100644 fn/googol.fn create mode 100644 fn/irrational.fn diff --git a/docs/ArithmeticTypes.drawio b/docs/ArithmeticTypes.drawio new file mode 100644 index 0000000..a272239 --- /dev/null +++ b/docs/ArithmeticTypes.drawio @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fn/googol.fn b/fn/googol.fn new file mode 100644 index 0000000..5a0e7fc --- /dev/null +++ b/fn/googol.fn @@ -0,0 +1 @@ +print(10 ** 100) diff --git a/fn/irrational.fn b/fn/irrational.fn new file mode 100644 index 0000000..4e0ed72 --- /dev/null +++ b/fn/irrational.fn @@ -0,0 +1 @@ +print(1.5) diff --git a/fn/rational.fn b/fn/rational.fn index 3c1511f..e2e2340 100644 --- a/fn/rational.fn +++ b/fn/rational.fn @@ -2,15 +2,14 @@ print(#( "1 * 2", 1 * 2 )); print(#( "1 + 2", 1 + 2 )); print(#( "2 / 3 + 4", 2 / 3 + 4 )); print(#( "4 + 2 / 3 + 4", 4 + 2 / 3 + 4 )); -print(#( "4 + 2 / -3 + 4", 4 + 2 / -3 + 4 )); +print(#( "4 + 4 / -6 + 4", 4 + 2 / -3 + 4 )); print(#( "2 / 3 + 4 / 5", 2 / 3 + 4 / 5 )); print(#( "(2 / 3) * (4 / 5)", (2 / 3) * (4 / 5) )); -print(#( "(6 / 5)", (6 / 5) )); +print(#( "(6 / 5)", (6 / 5) )); print(#( "(2 / 3) / (6 / 5)", (2 / 3) / (6 / 5) )); print(#( "(2 / 3) % (4 / 5)", (2 / 3) % (4 / 5) )); -print(#( "1914882942 ** 10", 1914882942 ** 10 )); -print(#( "1/3 % 8", 1/3 % 8 )); -print(#( "-9 % 8", -9 % 8 )); -print(#( "(1/2) ** 2", (1/2) ** 2 )); -print(#( "(1914882942 ** 5 / 5) % (2 / 3)", (1914882942 ** 5 / 5) % (2 / 3) )) - +print(#( "1/3 % 8", 1/3 % 8 )); +print(#( "-9 % 8", -9 % 8 )); +print(#( "(1/2) ** 2", (1/2) ** 2 )); +print(#( "1 / 2 < 1 / 3", 1/2 < 1/3 )); +print(#( "1 / 2 > 1 / 3", 1/2 > 1/3 )) diff --git a/src/arithmetic.c b/src/arithmetic.c index 595e801..1da495a 100644 --- a/src/arithmetic.c +++ b/src/arithmetic.c @@ -35,13 +35,14 @@ int rational_flag = 0; -IntegerBinOp add; -IntegerBinOp sub; -IntegerBinOp mul; -IntegerBinOp divide; -IntegerBinOp power; -IntegerBinOp modulo; -IntegerUnOp neg; +IntegerBinOp nadd; +IntegerBinOp nsub; +IntegerBinOp nmul; +IntegerBinOp ndiv; +IntegerBinOp npow; +IntegerBinOp nmod; +IntegerUnOp nneg; +CmpBinOp ncmp; static IntegerBinOp int_add; static IntegerBinOp int_sub; @@ -50,6 +51,7 @@ static IntegerBinOp int_divide; static IntegerBinOp int_power; static IntegerBinOp int_modulo; static IntegerUnOp int_neg; +static CmpBinOp int_cmp; static IntegerBinOp int_gcd; static CmpBinOp int_cmp; @@ -105,10 +107,12 @@ static Value intValue(int i) { # define ASSERT_STDINT(x) #endif -static int littleCmp(Value left, Value right) { +static ValueCmp littleCmp(Value left, Value right) { ASSERT_STDINT(left); ASSERT_STDINT(right); - return left.val.stdint < right.val.stdint ? -1 : left.val.stdint == right.val.stdint ? 0 : 1; + return left.val.stdint < right.val.stdint ? VALUE_CMP_LT : + left.val.stdint == right.val.stdint ? VALUE_CMP_EQ : + VALUE_CMP_GT; } static Value littleAdd(Value left, Value right) { @@ -198,12 +202,13 @@ static bool littleIsNeg(Value v) { # define ASSERT_BIGINT(x) #endif -static int bigCmp(Value left, Value right) { +static ValueCmp bigCmp(Value left, Value right) { ENTER(bigCmp); ASSERT_BIGINT(left); ASSERT_BIGINT(right); LEAVE(bigCmp); - return cmpBigInt(left.val.bigint, right.val.bigint); + int i = cmpBigInt(left.val.bigint, right.val.bigint); + return i < 0 ? VALUE_CMP_LT : i == 0 ? VALUE_CMP_EQ : VALUE_CMP_GT; } static Value bigIntValue(BigInt *i) { @@ -343,6 +348,22 @@ static bool bigIsNeg(Value v) { # define ASSERT_RATIONAL(x) #endif +static ValueCmp _rat_cmp(Value left, Value right) { + ENTER(_rat_cmp); + ASSERT_RATIONAL(left); + ASSERT_RATIONAL(right); + Value ad = int_mul(left.val.vec->values[NUMERATOR], + right.val.vec->values[DENOMINATOR]); + int save = protectValue(ad); + Value bc = int_mul(left.val.vec->values[DENOMINATOR], + right.val.vec->values[NUMERATOR]); + protectValue(bc); + ValueCmp res = int_cmp(ad, bc); + LEAVE(_rat_cmp); + UNPROTECT(save); + return res; +} + static Value makeRational(Value numerator, Value denominator) { Vec *vec = newVec(2); vec->values[NUMERATOR] = numerator; @@ -354,6 +375,32 @@ static Value makeRational(Value numerator, Value denominator) { return res; } +static ValueCmp ratCmp(Value left, Value right) { + ENTER(ratCmp); + ValueCmp res; + int save = PROTECT(NULL); + if (left.type == VALUE_TYPE_RATIONAL) { + if (right.type == VALUE_TYPE_RATIONAL) { + res = _rat_cmp(left, right); + } else { + right = makeRational(right, One); + protectValue(right); + res = _rat_cmp(left, right); + } + } else { + if (right.type == VALUE_TYPE_RATIONAL) { + left = makeRational(left, One); + protectValue(left); + res = _rat_cmp(left, right); + } else { + res = int_cmp(left, right); + } + } + LEAVE(ratCmp); + UNPROTECT(save); + return res; +} + static Value ratOp(Value left, Value right, ParameterizedBinOp op, IntegerBinOp intOp, bool simplify) { ENTER(ratOp); IFDEBUG(ppNumber(left)); @@ -624,29 +671,31 @@ void init_arithmetic() { int_power = littlePower; int_modulo = littleModulo; int_gcd = littleGcd; - int_cmp = littleCmp; int_neg_in_place = littleNegInPlace; int_neg = littleNeg; int_isneg = littleIsNeg; int_neg = littleNeg; + int_cmp = littleCmp; } if (rational_flag) { - add = ratAdd; - sub = ratSub; - mul = ratMul; - divide = ratDivide; - power = ratPower; - modulo = ratModulo; - neg = ratNeg; + nadd = ratAdd; + nsub = ratSub; + nmul = ratMul; + ndiv = ratDivide; + npow = ratPower; + nmod = ratModulo; + nneg = ratNeg; + ncmp = ratCmp; } else { - add = int_add; - mul = int_mul; - sub = int_sub; - divide = int_divide; - power = int_power; - modulo = int_modulo; - neg = int_neg; + nadd = int_add; + nmul = int_mul; + nsub = int_sub; + ndiv = int_divide; + npow = int_power; + nmod = int_modulo; + nneg = int_neg; + ncmp = int_cmp; } } diff --git a/src/arithmetic.h b/src/arithmetic.h index 0ff211f..9df9817 100644 --- a/src/arithmetic.h +++ b/src/arithmetic.h @@ -20,7 +20,7 @@ #include "value.h" -typedef int (*CmpBinOp)(Value, Value); +typedef ValueCmp (*CmpBinOp)(Value, Value); typedef Value (*IntegerBinOp)(Value, Value); typedef Value (*IntegerUnOp)(Value); typedef Value (*ParameterizedBinOp)(IntegerBinOp, Value, Value); @@ -29,13 +29,14 @@ typedef bool (*boolOp)(Value); extern int rational_flag; -extern IntegerBinOp add; -extern IntegerBinOp sub; -extern IntegerBinOp mul; -extern IntegerBinOp divide; -extern IntegerBinOp power; -extern IntegerBinOp modulo; -extern IntegerUnOp neg; +extern IntegerBinOp nadd; +extern IntegerBinOp nsub; +extern IntegerBinOp nmul; +extern IntegerBinOp ndiv; +extern IntegerBinOp npow; +extern IntegerBinOp nmod; +extern IntegerUnOp nneg; +extern CmpBinOp ncmp; void init_arithmetic(void); void markArithmetic(void); diff --git a/src/step.c b/src/step.c index 87a9292..bb07398 100644 --- a/src/step.c +++ b/src/step.c @@ -135,9 +135,9 @@ static bool truthy(Value v) { || v.type == VALUE_TYPE_VOID); } -static int _cmp(Value left, Value right); +static ValueCmp _cmp(Value left, Value right); -static int _vecCmp(Vec *left, Vec *right) { +static ValueCmp _vecCmp(Vec *left, Vec *right) { if (left == right) { return 0; } @@ -151,15 +151,15 @@ static int _vecCmp(Vec *left, Vec *right) { #endif for (int i = 0; i < left->size; ++i) { int cmp = _cmp(left->values[i], right->values[i]); - if (cmp != 0) + if (cmp != VALUE_CMP_EQ) return cmp; } - return 0; + return VALUE_CMP_EQ; } -#define _CMP_(left, right) ((left) < (right) ? -1 : (left) == (right) ? 0 : 1) +#define _CMP_(left, right) ((left) < (right) ? VALUE_CMP_LT : (left) == (right) ? VALUE_CMP_EQ : VALUE_CMP_GT) -static int _cmp(Value left, Value right) { +static ValueCmp _cmp(Value left, Value right) { #ifdef DEBUG_STEP eprintf("_cmp:\n"); printContainedValue(left, 0); @@ -176,9 +176,9 @@ static int _cmp(Value left, Value right) { case VALUE_TYPE_VOID: return 0; case VALUE_TYPE_BIGINT: - return cmpBigInt(left.val.bigint, right.val.bigint); case VALUE_TYPE_STDINT: - return _CMP_(left.val.stdint, right.val.stdint); + case VALUE_TYPE_RATIONAL: + return ncmp(left, right); case VALUE_TYPE_CHARACTER: return _CMP_(left.val.character, right.val.character); case VALUE_TYPE_CLO: @@ -193,13 +193,13 @@ static int _cmp(Value left, Value right) { } } -static Value cmp(Value left, Value right) { +static Value vcmp(Value left, Value right) { switch (_cmp(left, right)) { - case -1: + case VALUE_CMP_LT: return vLt; - case 0: + case VALUE_CMP_EQ: return vEq; - case 1: + case VALUE_CMP_GT: return vGt; default: cant_happen("unexpected value from _cmp"); @@ -207,15 +207,15 @@ static Value cmp(Value left, Value right) { } static bool _eq(Value left, Value right) { - return _cmp(left, right) == 0; + return _cmp(left, right) == VALUE_CMP_EQ; } static bool _gt(Value left, Value right) { - return _cmp(left, right) == 1; + return _cmp(left, right) == VALUE_CMP_GT; } static bool _lt(Value left, Value right) { - return _cmp(left, right) == -1; + return _cmp(left, right) == VALUE_CMP_LT; } static bool _xor(Value left, Value right) { @@ -480,7 +480,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(cmp(left, right)); + push(vcmp(left, right)); UNPROTECT(save); } break; @@ -491,7 +491,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(add(left, right)); + push(nadd(left, right)); UNPROTECT(save); } break; @@ -502,7 +502,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(sub(left, right)); + push(nsub(left, right)); UNPROTECT(save); } break; @@ -513,7 +513,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(mul(left, right)); + push(nmul(left, right)); UNPROTECT(save); } break; @@ -524,7 +524,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(divide(left, right)); + push(ndiv(left, right)); UNPROTECT(save); } break; @@ -535,7 +535,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(power(left, right)); + push(npow(left, right)); UNPROTECT(save); } break; @@ -546,7 +546,7 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(modulo(left, right)); + push(nmod(left, right)); UNPROTECT(save); } break; @@ -641,7 +641,7 @@ static void step() { DEBUGPRINTF("NEG\n"); Value a = pop(); int save = protectValue(a); - push(neg(a)); + push(nneg(a)); UNPROTECT(save); } break; diff --git a/src/value.h b/src/value.h index 83adb4c..8f2c5d6 100644 --- a/src/value.h +++ b/src/value.h @@ -20,6 +20,12 @@ # include "bigint.h" +typedef enum { + VALUE_CMP_LT = -1, + VALUE_CMP_EQ = 0, + VALUE_CMP_GT = 1 +} ValueCmp; + typedef enum { VALUE_TYPE_VOID, VALUE_TYPE_STDINT, From 21815a98ba2ac7062c2aeb55b0723125ae1daf63 Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sat, 6 Apr 2024 16:00:57 +0100 Subject: [PATCH 2/7] ensure all debugging still works --- fn/rational.fn | 4 +++- src/anf_normalize.c | 9 +++++---- src/anf_pp.c | 6 ++++++ src/desugaring.c | 5 +++-- src/hash.c | 28 ---------------------------- src/lambda_pp.c | 5 ++++- src/step.c | 17 ++++++++++++++++- tools/makeAST.py | 25 +++++++++++++++++++++---- utils.sh | 2 +- 9 files changed, 59 insertions(+), 42 deletions(-) diff --git a/fn/rational.fn b/fn/rational.fn index e2e2340..c8bc38f 100644 --- a/fn/rational.fn +++ b/fn/rational.fn @@ -12,4 +12,6 @@ print(#( "1/3 % 8", 1/3 % 8 )); print(#( "-9 % 8", -9 % 8 )); print(#( "(1/2) ** 2", (1/2) ** 2 )); print(#( "1 / 2 < 1 / 3", 1/2 < 1/3 )); -print(#( "1 / 2 > 1 / 3", 1/2 > 1/3 )) +print(#( "1 / 2 > 1 / 3", 1/2 > 1/3 )); +print(#( "1 / 2 < 1", 1/2 < 1 )); +print(#( "1 / 2 > 1", 1/2 > 1 )) diff --git a/src/anf_normalize.c b/src/anf_normalize.c index f801d64..e8ff8ff 100644 --- a/src/anf_normalize.c +++ b/src/anf_normalize.c @@ -29,6 +29,7 @@ # include # include "debug.h" # include "lambda_pp.h" +# include "anf_debug.h" # include "debugging_on.h" #else # include "debugging_off.h" @@ -750,7 +751,7 @@ static Exp *normalizeApply(LamApply *lamApply, Exp *tail) { AexpList *args = replaceLamList(lamApply->args, replacements); PROTECT(args); DEBUG("back from replaceLamList"); - IFDEBUG(printHashTable(replacements, 0)); + IFDEBUG(printLamExpTable(replacements, 0)); CexpApply *cexpApply = newCexpApply(function, countAexpList(args), args); UNPROTECT(save2); save2 = PROTECT(cexpApply); @@ -770,8 +771,8 @@ static Exp *normalizeApply(LamApply *lamApply, Exp *tail) { static Exp *letBind(Exp *body, LamExpTable *replacements) { ENTER(letBind); // DEBUG("sleep %d", sleep(1)); - IFDEBUG(printExp(body)); - IFDEBUG(printHashTable(replacements, 0)); + IFDEBUG(printExp(body, 0)); + IFDEBUG(printLamExpTable(replacements, 0)); if (countLamExpTable(replacements) == 0) { LEAVE(letBind); return body; @@ -1181,7 +1182,7 @@ static Aexp *replaceLamCexp(LamExp *apply, LamExpTable *replacements) { } HashSymbol *subst = freshSymbol(); setLamExpTable(replacements, subst, apply); - IFDEBUG(printHashTable(replacements, 0)); + IFDEBUG(printLamExpTable(replacements, 0)); LEAVE(replaceLamCexp); return newAexp(AEXP_TYPE_VAR, AEXP_VAL_VAR(subst)); } diff --git a/src/anf_pp.c b/src/anf_pp.c index 1077d79..cfbfdbe 100644 --- a/src/anf_pp.c +++ b/src/anf_pp.c @@ -118,6 +118,9 @@ void ppAexpPrimApp(AexpPrimApp *x) { case AEXPPRIMOP_TYPE_CMP: eprintf("cmp "); break; + case AEXPPRIMOP_TYPE_POW: + eprintf("pow "); + break; default: cant_happen("unrecognized op %s", aexpPrimOpName(x->type)); } @@ -132,6 +135,9 @@ void ppAexpPrimApp(AexpPrimApp *x) { void ppAexpUnaryApp(AexpUnaryApp *x) { eprintf("("); switch (x->type) { + case AEXPUNARYOP_TYPE_NEG: + eprintf("neg "); + break; case AEXPUNARYOP_TYPE_NOT: eprintf("not "); break; diff --git a/src/desugaring.c b/src/desugaring.c index 2a310e8..3a82401 100644 --- a/src/desugaring.c +++ b/src/desugaring.c @@ -24,6 +24,7 @@ #include "common.h" #include "desugaring.h" #include "symbol.h" +#include "anf_pp.h" #ifdef DEBUG_DESUGARING # include "debug.h" @@ -45,7 +46,7 @@ static Aexp *desugarAexp(Aexp *x); static Cexp *desugarCexp(Cexp *x); #ifdef DEBUG_DESUGARING -# define DEBUG_DESUGAR(type, val) do { printf("desugar" #type ": "); print ## type (val); printf("\n"); } while(0) +# define DEBUG_DESUGAR(type, val) do { printf("desugar" #type ": "); pp ## type (val); printf("\n"); } while(0) #else # define DEBUG_DESUGAR(type, val) do {} while(0) #endif @@ -70,7 +71,7 @@ static AexpUnaryApp *desugarAexpUnaryApp(AexpUnaryApp *x) { } static HashSymbol *desugarAexpVar(HashSymbol *x) { - DEBUG_DESUGAR(HashSymbol, x); + DEBUG_DESUGAR(AexpVar, x); return x; } diff --git a/src/hash.c b/src/hash.c index 6aea652..2b7ac44 100644 --- a/src/hash.c +++ b/src/hash.c @@ -41,23 +41,6 @@ static int idCounter = 0; bool hash_debug_flag = false; #endif -#ifdef DEBUG_HASHTABLE -static void printMemHeader(char *id, void *ptr) { - /* - if (ptr == NULL) return; - int size = 16; - - char *b = (char *)ptr; - b -= size; - eprintf("%s mem header", id); - for (int i = 0; i < size; i++) { - eprintf(" %02x", b[i]); - } - eprintf("\n"); - */ -} -#endif - HashTable *newHashTable(size_t valuesize, MarkHashValueFunction markfunction, PrintHashValueFunction printfunction) { DEBUG("newHashTable() [id=%d, valuesize=%lu]", idCounter, valuesize); @@ -105,7 +88,6 @@ static void growCapacity(HashTable *table, int capacity) { DEBUG("growCapacity(%d) [%d]", capacity, table->id); HashSymbol **keys = NEW_ARRAY(HashSymbol *, capacity); DEBUG("growCapacity old keys: %p new keys: %p", table->keys, keys); - IFDEBUG(printMemHeader("keys", keys)); void *values = NULL; for (int i = 0; i < capacity; i++) { @@ -117,7 +99,6 @@ static void growCapacity(HashTable *table, int capacity) { bzero(values, table->valuesize * capacity); DEBUG("growCapacity old values: %p new values: %p", table->values, values); - IFDEBUG(printMemHeader("values", values)); } for (int old_index = 0; old_index < table->capacity; old_index++) { @@ -187,8 +168,6 @@ bool hashContains(HashTable *table, HashSymbol *var) { bool hashGet(HashTable *table, HashSymbol *var, void *dest) { DEBUG("hashGet(%s) [%d]", var->name, table->id); - IFDEBUG(printMemHeader("values", table->values)); - IFDEBUG(printMemHeader("keys", table->keys)); if (table->count == 0) return false; hash_t index = findEntry(table->keys, table->capacity, var); @@ -203,8 +182,6 @@ bool hashGet(HashTable *table, HashSymbol *var, void *dest) { HashSymbol *hashGetVar(HashTable *table, const char *name) { DEBUG("hashGetVar() [%d]", table->id); - IFDEBUG(printMemHeader("values", table->values)); - IFDEBUG(printMemHeader("keys", table->keys)); if (table->count == 0) return NULL; hash_t hash = hashString(name); @@ -229,8 +206,6 @@ void markHashTable(HashTable *table) { if (table == NULL) return; DEBUG("markHashTable() [%d]", table->id); - IFDEBUG(printMemHeader("values", table->values)); - IFDEBUG(printMemHeader("keys", table->keys)); if (MARKED(table)) return; MARK(table); @@ -250,8 +225,6 @@ void markHashTable(HashTable *table) { void freeHashTableObj(Header *h) { HashTable *table = (HashTable *) h; DEBUG("freeHashTableObj() [%d]", table->id); - IFDEBUG(printMemHeader("values", table->values)); - IFDEBUG(printMemHeader("keys", table->keys)); if (table == NULL) return; if (table->count > 0) { @@ -259,7 +232,6 @@ void freeHashTableObj(Header *h) { FREE_ARRAY(HashSymbol *, table->keys, table->capacity); if (table->valuesize > 0) { DEBUG("freeHashTableObj values: %p", table->values); - IFDEBUG(printMemHeader("values", table->values)); FREE_ARRAY(char, table->values, table->capacity * table->valuesize); } diff --git a/src/lambda_pp.c b/src/lambda_pp.c index b50329e..3c18daf 100644 --- a/src/lambda_pp.c +++ b/src/lambda_pp.c @@ -283,6 +283,9 @@ void ppLamUnary(LamUnaryApp *unaryApp) { void ppLamUnaryOp(LamUnaryOp type) { switch (type) { + case LAMUNARYOP_TYPE_NEG: + eprintf("neg"); + break; case LAMUNARYOP_TYPE_NOT: eprintf("not"); break; @@ -296,7 +299,7 @@ void ppLamUnaryOp(LamUnaryOp type) { eprintf("putv"); break; default: - cant_happen("unrecognised type %d in ppLamUnaryOp", type); + cant_happen("unrecognised type %s in ppLamUnaryOp", lamUnaryOpName(type)); } } diff --git a/src/step.c b/src/step.c index bb07398..e6780ee 100644 --- a/src/step.c +++ b/src/step.c @@ -169,7 +169,22 @@ static ValueCmp _cmp(Value left, Value right) { #endif #ifdef SAFETY_CHECKS if (left.type != right.type) { - cant_happen("different types in _cmp"); + switch (left.type) { + case VALUE_TYPE_BIGINT: + case VALUE_TYPE_STDINT: + case VALUE_TYPE_RATIONAL: + switch (right.type) { + case VALUE_TYPE_BIGINT: + case VALUE_TYPE_STDINT: + case VALUE_TYPE_RATIONAL: + break; + default: + cant_happen("different types in _cmp"); + } + break; + default: + cant_happen("different types in _cmp"); + } } #endif switch (left.type) { diff --git a/tools/makeAST.py b/tools/makeAST.py index b48a3a3..42621ca 100644 --- a/tools/makeAST.py +++ b/tools/makeAST.py @@ -663,6 +663,23 @@ def printTypedef(self, catalog): print(f'}} {myName}; // SimpleHash.printTypedef') print('') + def getPrintSignature(self, catalog): + myType = self.getTypeDeclaration() + myName = self.getName() + return f"void print{myName}({myType} x, int depth)" + + def printPrintDeclaration(self, catalog): + decl = self.getPrintSignature(catalog); + print(f"{decl}; // SimpleHash.printPrintDeclaration") + + def printPrintFunction(self, catalog): + decl = self.getPrintSignature(catalog); + comment = "// SimpleHash.printPrintFunction" + print(f"{decl} {{ {comment}") + print(f" printHashTable(&(x->wrapped), depth); {comment}") + print(f"}} {comment}") + print("") + def printCopyField(self, field, depth, prefix=''): myConstructor = self.getConstructorName() print(f' x->{prefix}{field} = {myConstructor}(); // SimpleHash.printCopyField') @@ -689,10 +706,10 @@ def printNewFunction(self, catalog): printFn = 'NULL' else: size = f'sizeof({self.entries.getTypeDeclaration(catalog)})' - printFn = f'print{myName}' + printFn = f'_print{myName}' if self.entries.hasMarkFn(catalog): - markFn = f'mark{myName}' - print(f'static void mark{myName}(void *ptr) {{ // SimpleHash.printNewFunction') + markFn = f'_mark{myName}' + print(f'static void {markFn}(void *ptr) {{ // SimpleHash.printNewFunction') self.entries.printMarkHashLine(catalog, 1) print('} // SimpleHash.printNewFunction') print('') @@ -700,7 +717,7 @@ def printNewFunction(self, catalog): markFn = 'NULL' self.entries.printPrintDeclaration(catalog) print('') - print(f'static void print{myName}(void *ptr, int depth) {{ // SimpleHash.printNewFunction') + print(f'static void {printFn}(void *ptr, int depth) {{ // SimpleHash.printNewFunction') self.entries.printPrintHashLine(catalog, 1); print('}') print('') diff --git a/utils.sh b/utils.sh index bbad0c5..9e74edd 100644 --- a/utils.sh +++ b/utils.sh @@ -1,3 +1,3 @@ fnd () { - grep -rwn $1 src + grep -rwn $1 src generated } From ae8d396d59b29da2b1b2d02ea4f02593390be74c Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sat, 6 Apr 2024 16:36:25 +0100 Subject: [PATCH 3/7] the --report flag now reports compile- and run-times separately --- src/main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index bce70ef..d1e8429 100644 --- a/src/main.c +++ b/src/main.c @@ -161,11 +161,16 @@ static ByteCodeArray generateByteCodes(Exp *anfExp) { return byteCodes; } -static void report(clock_t begin) { +static void report(clock_t begin, clock_t compiled) { if (report_flag) { clock_t end = clock(); + printf("\n"); double time_spent = (double) (end - begin) / CLOCKS_PER_SEC; - printf("\nelapsed time %.3lf\n", time_spent); + printf("elapsed time %.3lf\n", time_spent); + double compile_time = (double) (compiled - begin) / CLOCKS_PER_SEC; + printf("compile time %.3lf\n", compile_time); + double run_time = (double) (end - compiled) / CLOCKS_PER_SEC; + printf("run time %.3lf\n", run_time); reportMemory(); reportSteps(); } @@ -201,9 +206,11 @@ int main(int argc, char *argv[]) { UNPROTECT(save); + clock_t compiled = clock(); + run(byteCodes); - report(begin); + report(begin, compiled); exit(0); } From 7860dc60b1dcb7849b0fc01cb2aafb193b5028a1 Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sun, 7 Apr 2024 16:03:21 +0100 Subject: [PATCH 4/7] bigints and stdints mix freely, no --bigint option --- docs/TODO.md | 2 + src/anf.yaml | 4 +- src/anf_normalize.c | 20 +- src/anf_pp.c | 4 +- src/arithmetic.c | 570 ++++++++++++++++++++++++------------------- src/arithmetic.h | 3 +- src/ast.yaml | 4 +- src/bigint.c | 244 ++++++++++++++---- src/bigint.h | 44 +++- src/bytecode.c | 16 +- src/common.h | 2 +- src/debug.c | 24 +- src/lambda.yaml | 4 +- src/lambda_pp.c | 4 +- src/main.c | 2 - src/memory.c | 3 + src/memory.h | 1 + src/parser.y | 69 +++++- src/primitives.yaml | 7 + src/step.c | 93 ++++--- src/tpmc.yaml | 2 +- src/tpmc_compare.c | 2 +- src/tpmc_logic.c | 4 +- src/tpmc_match.c | 2 +- src/tpmc_mermaid.c | 2 +- src/tpmc_pp.c | 2 +- src/tpmc_translate.c | 4 +- src/value.h | 6 - 28 files changed, 735 insertions(+), 409 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index 08ac58f..84032a7 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -11,6 +11,7 @@ * NaN. * Improve arithmetic. * General overhaul. + * move to [libgmp](https://gmplib.org/) * Pre-compute constant values at compile time. * allow numeric (not symbolic) arithmetic expressions in patterns. * allow unpacking of numerator and denominator variables in patterns. @@ -31,3 +32,4 @@ * User definable infix operators. * With precedence and associativity. * Curried binary operators `(2+)` etc. +* Allow trailing semicolons ffs. diff --git a/src/anf.yaml b/src/anf.yaml index fce0b7e..4655310 100644 --- a/src/anf.yaml +++ b/src/anf.yaml @@ -84,7 +84,7 @@ structs: cases: CexpCondCases CexpIntCondCases: - option: BigInt + option: MaybeBigInt body: Exp next: CexpIntCondCases @@ -141,7 +141,7 @@ unions: lam: AexpLam var: HashSymbol annotatedVar: AexpAnnotatedVar - biginteger: BigInt + biginteger: MaybeBigInt littleinteger: int character: char prim: AexpPrimApp diff --git a/src/anf_normalize.c b/src/anf_normalize.c index e8ff8ff..44a3085 100644 --- a/src/anf_normalize.c +++ b/src/anf_normalize.c @@ -38,7 +38,7 @@ static Exp *normalize(LamExp *lamExp, Exp *tail); static Exp *normalizeLam(LamLam *lamLam, Exp *tail); static Exp *normalizeVar(HashSymbol *var, Exp *tail); -static Exp *normalizeBigInteger(BigInt *integer, Exp *tail); +static Exp *normalizeMaybeBigInteger(MaybeBigInt *integer, Exp *tail); static Exp *normalizeStdInteger(int integer, Exp *tail); static Exp *normalizeCharacter(char character, Exp *tail); static Exp *normalizeUnary(LamUnaryApp *app, Exp *tail); @@ -57,7 +57,7 @@ static AexpUnaryOp mapUnaryOp(LamUnaryOp op); static Exp *letBind(Exp *body, LamExpTable *replacements); static AexpPrimOp mapPrimOp(LamPrimOp op); static Aexp *aexpNormalizeVar(HashSymbol *var); -static Aexp *aexpNormalizeBigInteger(BigInt *integer); +static Aexp *aexpNormalizeMaybeBigInteger(MaybeBigInt *integer); static Aexp *aexpNormalizeStdInteger(int integer); static Aexp *aexpNormalizeCharacter(char character); static Aexp *aexpNormalizeLam(LamLam *lamLam); @@ -108,7 +108,7 @@ static Exp *normalize(LamExp *lamExp, Exp *tail) { case LAMEXP_TYPE_STDINT: return normalizeStdInteger(lamExp->val.stdint, tail); case LAMEXP_TYPE_BIGINTEGER: - return normalizeBigInteger(lamExp->val.biginteger, tail); + return normalizeMaybeBigInteger(lamExp->val.biginteger, tail); case LAMEXP_TYPE_PRIM: return normalizePrim(lamExp->val.prim, tail); case LAMEXP_TYPE_UNARY: @@ -652,17 +652,17 @@ static Exp *normalizeCharacter(char character, Exp *tail) { return exp; } -static Exp *normalizeBigInteger(BigInt *integer, Exp *tail) { - ENTER(normalizeBigInteger); +static Exp *normalizeMaybeBigInteger(MaybeBigInt *integer, Exp *tail) { + ENTER(normalizeMaybeBigInteger); if (tail != NULL) { - LEAVE(normalizeBigInteger); + LEAVE(normalizeMaybeBigInteger); return tail; } - Aexp *aexp = aexpNormalizeBigInteger(integer); + Aexp *aexp = aexpNormalizeMaybeBigInteger(integer); int save = PROTECT(aexp); Exp *exp = wrapAexp(aexp); UNPROTECT(save); - LEAVE(normalizeBigInteger); + LEAVE(normalizeMaybeBigInteger); return exp; } @@ -801,7 +801,7 @@ static Aexp *aexpNormalizeVar(HashSymbol *var) { return newAexp(AEXP_TYPE_VAR, AEXP_VAL_VAR(var)); } -static Aexp *aexpNormalizeBigInteger(BigInt *integer) { +static Aexp *aexpNormalizeMaybeBigInteger(MaybeBigInt *integer) { return newAexp(AEXP_TYPE_BIGINTEGER, AEXP_VAL_BIGINTEGER(integer)); } @@ -902,7 +902,7 @@ static Aexp *replaceLamExp(LamExp *lamExp, LamExpTable *replacements) { res = aexpNormalizeVar(lamExp->val.var); break; case LAMEXP_TYPE_BIGINTEGER: - res = aexpNormalizeBigInteger(lamExp->val.biginteger); + res = aexpNormalizeMaybeBigInteger(lamExp->val.biginteger); break; case LAMEXP_TYPE_STDINT: res = aexpNormalizeStdInteger(lamExp->val.stdint); diff --git a/src/anf_pp.c b/src/anf_pp.c index cfbfdbe..62723ce 100644 --- a/src/anf_pp.c +++ b/src/anf_pp.c @@ -240,7 +240,7 @@ void ppCexpCond(CexpCond *x) { void ppCexpIntCondCases(CexpIntCondCases *x) { while (x != NULL) { eprintf("("); - fprintBigInt(errout, x->option); + fprintMaybeBigInt(errout, x->option); eprintf(" "); ppExp(x->body); eprintf(")"); @@ -378,7 +378,7 @@ void ppAexp(Aexp *x) { eprintf("nil"); break; case AEXP_TYPE_BIGINTEGER: - fprintBigInt(errout, x->val.biginteger); + fprintMaybeBigInt(errout, x->val.biginteger); break; case AEXP_TYPE_LITTLEINTEGER: eprintf("%d", x->val.littleinteger); diff --git a/src/arithmetic.c b/src/arithmetic.c index 1da495a..bd8c996 100644 --- a/src/arithmetic.c +++ b/src/arithmetic.c @@ -17,6 +17,7 @@ */ #include +#include #include "common.h" #include "bigint.h" @@ -44,20 +45,6 @@ IntegerBinOp nmod; IntegerUnOp nneg; CmpBinOp ncmp; -static IntegerBinOp int_add; -static IntegerBinOp int_sub; -static IntegerBinOp int_mul; -static IntegerBinOp int_divide; -static IntegerBinOp int_power; -static IntegerBinOp int_modulo; -static IntegerUnOp int_neg; -static CmpBinOp int_cmp; - -static IntegerBinOp int_gcd; -static CmpBinOp int_cmp; -static voidOp int_neg_in_place; -static boolOp int_isneg; - static Value One = { .type = VALUE_TYPE_STDINT, .val = VALUE_VAL_STDINT(1) @@ -90,9 +77,7 @@ static void ppNumber(Value number) { } #endif -//////////////////////////////// -// fixed size integer operations -//////////////////////////////// +#define IS_BIGINT(x) ((x).type == VALUE_TYPE_BIGINT) static Value intValue(int i) { Value val; @@ -101,246 +86,343 @@ static Value intValue(int i) { return val; } -#ifdef SAFETY_CHECKS -# define ASSERT_STDINT(x) ASSERT((x).type == VALUE_TYPE_STDINT) -#else -# define ASSERT_STDINT(x) -#endif - -static ValueCmp littleCmp(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return left.val.stdint < right.val.stdint ? VALUE_CMP_LT : - left.val.stdint == right.val.stdint ? VALUE_CMP_EQ : - VALUE_CMP_GT; -} - -static Value littleAdd(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return intValue(left.val.stdint + right.val.stdint); -} - -static Value littleMul(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return intValue(left.val.stdint * right.val.stdint); -} - -static Value littleSub(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return intValue(left.val.stdint - right.val.stdint); +static Value bigIntValue(BigInt *i) { + Value val; + val.type = VALUE_TYPE_BIGINT; + val.val = VALUE_VAL_BIGINT(i); + return val; } -static Value littleDivide(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - if (littleCmp(right, Zero) == 0) { - cant_happen("attempted div zero"); +static Cmp int_cmp(Value left, Value right) { + ENTER(int_cmp); + Cmp res; + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + res = cmpBigInt(left.val.bigint, right.val.bigint); + } else { + res = cmpBigIntInt(left.val.bigint, right.val.stdint); + } + } else { + if (IS_BIGINT(right)) { + res = cmpIntBigInt(left.val.stdint, right.val.bigint); + } else { + res = left.val.stdint < right.val.stdint ? CMP_LT : + left.val.stdint == right.val.stdint ? CMP_EQ : + CMP_GT; + } } - return intValue(left.val.stdint / right.val.stdint); -} - -static Value littlePower(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return intValue(pow(left.val.stdint, right.val.stdint)); + LEAVE(int_cmp); + return res; } -static Value littleModulo(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - if (littleCmp(right, Zero) == 0) { - cant_happen("attempted mod zero"); +static Value safe_add(int a, int b) { + int c; + if (__builtin_add_overflow(a, b, &c)) { + BigInt *big = bigIntFromAddition(a, b); + int save = PROTECT(big); + Value res = bigIntValue(big); + UNPROTECT(save); + return res; + } else { + return intValue(c); } - return intValue(left.val.stdint % right.val.stdint); -} - -static int gcd (int a, int b) { - int i = 0, min_num = a, gcd = 1; - if (a > b) { - min_num = b; - } - for (i = 1; i <= min_num; i++) { - if (a % i == 0 && b % i == 0) { - gcd = i; - } - } - return gcd; } -static Value littleGcd(Value left, Value right) { - ASSERT_STDINT(left); - ASSERT_STDINT(right); - return intValue(gcd(left.val.stdint, right.val.stdint)); -} - -static void littleNegInPlace(Value *v) { - ASSERT_STDINT(*v); - v->val.stdint = -(v->val.stdint); -} - -static Value littleNeg(Value v) { - ASSERT_STDINT(v); - v.val.stdint = -(v.val.stdint); - return v; +static Value int_add(Value left, Value right) { + ENTER(int_add); + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + BigInt *b = addBigInt(left.val.bigint, right.val.bigint); + PROTECT(b); + res = bigIntValue(b); + } else { + BigInt *b = addBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(b); + res = bigIntValue(b); + } + } else { + if (IS_BIGINT(right)) { + BigInt *b = addBigIntInt(right.val.bigint, left.val.stdint); + PROTECT(b); + res = bigIntValue(b); + } else { + res = safe_add(left.val.stdint, right.val.stdint); + } + } + LEAVE(int_add); + UNPROTECT(save); + return res; } -static bool littleIsNeg(Value v) { - ASSERT_STDINT(v); - return v.val.stdint < 0; +static Value safe_mul(int a, int b) { + int c; + if (__builtin_mul_overflow(a, b, &c)) { + BigInt *big = bigIntFromMultiplication(a, b); + int save = PROTECT(big); + Value res = bigIntValue(big); + UNPROTECT(save); + return res; + } else { + return intValue(c); + } } -//////////////////////////////////// -// arbitrary size integer operations -//////////////////////////////////// - -#ifdef SAFETY_CHECKS -# define ASSERT_BIGINT(x) ASSERT((x).type == VALUE_TYPE_BIGINT) -#else -# define ASSERT_BIGINT(x) -#endif - -static ValueCmp bigCmp(Value left, Value right) { - ENTER(bigCmp); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - LEAVE(bigCmp); - int i = cmpBigInt(left.val.bigint, right.val.bigint); - return i < 0 ? VALUE_CMP_LT : i == 0 ? VALUE_CMP_EQ : VALUE_CMP_GT; +static Value int_mul(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + BigInt *bi = mulBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + BigInt *bi = mulBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(right)) { + BigInt *bi = mulBigIntInt(right.val.bigint, left.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + res = safe_mul(left.val.stdint, right.val.stdint); + } + } + UNPROTECT(save); + return res; } -static Value bigIntValue(BigInt *i) { - Value val; - val.type = VALUE_TYPE_BIGINT; - val.val = VALUE_VAL_BIGINT(i); - return val; +static Value safe_sub(int a, int b) { + int c; + if (__builtin_sub_overflow(a, b, &c)) { + BigInt *big = bigIntFromSubtraction(a, b); + int save = PROTECT(big); + Value res = bigIntValue(big); + UNPROTECT(save); + return res; + } else { + return intValue(c); + } } -static Value bigAdd(Value left, Value right) { - ENTER(bigAdd); - IFDEBUG(ppNumber(left)); - IFDEBUG(ppNumber(right)); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - BigInt *result = addBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - LEAVE(bigAdd); +static Value int_sub(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + BigInt *bi = subBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + BigInt *bi = subBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(right)) { + BigInt *bi = subIntBigInt(left.val.stdint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + res = safe_sub(left.val.stdint, right.val.stdint); + } + } UNPROTECT(save); return res; } -static Value bigMul(Value left, Value right) { - ENTER(bigMul); - IFDEBUG(ppNumber(left)); - IFDEBUG(ppNumber(right)); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - BigInt *result = mulBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - LEAVE(bigMul); +static Value int_div(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + if (int_cmp(right, Zero) == CMP_EQ) { + cant_happen("attempted div zero"); + } + BigInt *bi = divBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + if (right.val.stdint == 0) { + cant_happen("attempted div zero"); + } + BigInt *bi = divBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(right)) { + if (int_cmp(right, Zero) == CMP_EQ) { + cant_happen("attempted div zero"); + } + BigInt *bi = divIntBigInt(left.val.stdint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + if (right.val.stdint == 0) { + cant_happen("attempted div zero"); + } + // division can't overflow + res = intValue(left.val.stdint / right.val.stdint); + } + } UNPROTECT(save); return res; } -static Value bigSub(Value left, Value right) { - ENTER(bigSub); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - BigInt *result = subBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - LEAVE(bigSub); - UNPROTECT(save); - return res; +static Value safe_pow(int a, int b) { + float f = powf((float) a, (float) b); + if (f == HUGE_VALF || f > (float)INT_MAX || f < (float)INT_MIN) { + BigInt *big = bigIntFromPower(a, b); + int save = PROTECT(big); + Value res = bigIntValue(big); + UNPROTECT(save); + return res; + } else { + return intValue((int) f); + } } -static Value bigDivide(Value left, Value right) { - ENTER(bigDivide); - IFDEBUG(ppNumber(left)); - IFDEBUG(ppNumber(right)); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - if (bigCmp(right, Zero) == 0) { - cant_happen("attempted div zero"); +static Value int_pow(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + BigInt *bi = powBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + BigInt *bi = powBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(right)) { + BigInt *bi = powIntBigInt(left.val.stdint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + res = safe_pow(left.val.stdint, right.val.stdint); + } } - BigInt *result = divBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - protectValue(res); - LEAVE(bigDivide); - IFDEBUG(ppNumber(res)); UNPROTECT(save); return res; } -static Value bigPower(Value left, Value right) { - ENTER(bigPower); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - BigInt *result = powBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - LEAVE(bigPower); +static Value int_mod(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + if (int_cmp(right, Zero) == CMP_EQ) { + cant_happen("attempted mod zero"); + } + BigInt *bi = modBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + if (right.val.stdint == 0) { + cant_happen("attempted mod zero"); + } + BigInt *bi = modBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(right)) { + if (int_cmp(right, Zero) == CMP_EQ) { + cant_happen("attempted mod zero"); + } + BigInt *bi = modIntBigInt(left.val.stdint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + if (right.val.stdint == 0) { + cant_happen("attempted mod zero"); + } + // modulus can't overflow + res = intValue(left.val.stdint % right.val.stdint); + } + } UNPROTECT(save); return res; } -static Value bigModulo(Value left, Value right) { - ENTER(bigModulo); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - if (bigCmp(right, Zero) == 0) { - cant_happen("attempted mod zero"); - } - BigInt *result = modBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(result); - Value res = bigIntValue(result); - LEAVE(bigModulo); - UNPROTECT(save); - return res; +static int gcd (int a, int b) { + int i = 0, min_num = a, gcd = 1; + if (a > b) { + min_num = b; + } + for (i = 1; i <= min_num; i++) { + if (a % i == 0 && b % i == 0) { + gcd = i; + } + } + return gcd; } -static Value bigGcd(Value left, Value right) { - ENTER(bigGcd); - ASSERT_BIGINT(left); - ASSERT_BIGINT(right); - BigInt *gcd = gcdBigInt(left.val.bigint, right.val.bigint); - int save = PROTECT(gcd); - Value res = bigIntValue(gcd); - LEAVE(bigGcd); +static Value int_gcd(Value left, Value right) { + Value res; + int save = PROTECT(NULL); + if (IS_BIGINT(left)) { + if (IS_BIGINT(right)) { + BigInt *bi = gcdBigInt(left.val.bigint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + BigInt *bi = gcdBigIntInt(left.val.bigint, right.val.stdint); + PROTECT(bi); + res = bigIntValue(bi); + } + } else { + if (IS_BIGINT(left)) { + BigInt *bi = gcdIntBigInt(left.val.stdint, right.val.bigint); + PROTECT(bi); + res = bigIntValue(bi); + } else { + res = intValue(gcd(left.val.stdint, right.val.stdint)); + } + } UNPROTECT(save); return res; } -static Value bigNeg(Value v) { - ENTER(bigNeg); - ASSERT_BIGINT(v); - BigInt *bi = copyBigInt(v.val.bigint); - int save = PROTECT(bi); - negateBigInt(bi); - Value res = bigIntValue(bi); - LEAVE(bigNeg); - UNPROTECT(save); - return res; +static void int_neg_in_place(Value *v) { + if (IS_BIGINT(*v)) { + negateBigInt(v->val.bigint); + } else { + v->val.stdint = -(v->val.stdint); + } } -static void bigNegInPlace(Value *v) { - ASSERT_BIGINT(*v); - negateBigInt(v->val.bigint); +static Value int_neg(Value v) { + int save = PROTECT(NULL); + if (IS_BIGINT(v)) { + BigInt *bi = copyBigInt(v.val.bigint); + PROTECT(bi); + negateBigInt(bi); + v = bigIntValue(bi); + } else { + v.val.stdint = -(v.val.stdint); + } + UNPROTECT(save); + return v; } -static bool bigIsNeg(Value v) { - ASSERT_BIGINT(v); - return isNegBigInt(v.val.bigint); +static bool int_isneg(Value v) { + if (IS_BIGINT(v)) { + return isNegBigInt(v.val.bigint); + } else { + return v.val.stdint < 0; + } } -/////////////////////////////////////// -// unspecified size rational operations -/////////////////////////////////////// +//////////////////////// +// rational operations +//////////////////////// #ifdef SAFETY_CHECKS # define ASSERT_RATIONAL(x) ASSERT((x).type == VALUE_TYPE_RATIONAL) @@ -348,7 +430,7 @@ static bool bigIsNeg(Value v) { # define ASSERT_RATIONAL(x) #endif -static ValueCmp _rat_cmp(Value left, Value right) { +static Cmp _rat_cmp(Value left, Value right) { ENTER(_rat_cmp); ASSERT_RATIONAL(left); ASSERT_RATIONAL(right); @@ -358,7 +440,7 @@ static ValueCmp _rat_cmp(Value left, Value right) { Value bc = int_mul(left.val.vec->values[DENOMINATOR], right.val.vec->values[NUMERATOR]); protectValue(bc); - ValueCmp res = int_cmp(ad, bc); + Cmp res = int_cmp(ad, bc); LEAVE(_rat_cmp); UNPROTECT(save); return res; @@ -375,9 +457,9 @@ static Value makeRational(Value numerator, Value denominator) { return res; } -static ValueCmp ratCmp(Value left, Value right) { +static Cmp ratCmp(Value left, Value right) { ENTER(ratCmp); - ValueCmp res; + Cmp res; int save = PROTECT(NULL); if (left.type == VALUE_TYPE_RATIONAL) { if (right.type == VALUE_TYPE_RATIONAL) { @@ -453,17 +535,17 @@ static Value ratSimplify(Value numerator, Value denominator) { Value gcd = int_gcd(numerator, denominator); int save = protectValue(gcd); Value res; - if (int_cmp(gcd, One) != 0) { - numerator = int_divide(numerator, gcd); + if (int_cmp(gcd, One) != CMP_EQ) { + numerator = int_div(numerator, gcd); protectValue(numerator); - denominator = int_divide(denominator, gcd); + denominator = int_div(denominator, gcd); protectValue(denominator); } if (int_isneg(denominator)) { int_neg_in_place(&numerator); int_neg_in_place(&denominator); } - if (int_cmp(denominator, One) == 0) { + if (int_cmp(denominator, One) == CMP_EQ) { res = numerator; } else { res = makeRational(numerator, denominator); @@ -578,7 +660,7 @@ static Value ratDivide(Value left, Value right) { static Value ratModulo(Value left, Value right) { ENTER(ratModulo); - Value res = ratOp(left, right, _rat_add_sub, int_modulo, true); + Value res = ratOp(left, right, _rat_add_sub, int_mod, true); LEAVE(ratModulo); return res; } @@ -588,9 +670,9 @@ static Value _ratPower(Value left, Value right) { ASSERT_RATIONAL(left); Value numerator = left.val.vec->values[NUMERATOR]; Value denominator = left.val.vec->values[DENOMINATOR]; - numerator = int_power(numerator, right); + numerator = int_pow(numerator, right); int save = protectValue(numerator); - denominator = int_power(denominator, right); + denominator = int_pow(denominator, right); protectValue(denominator); Value res = ratSimplify(numerator, denominator); protectValue(res); @@ -620,7 +702,7 @@ static Value ratPower(Value left, Value right) { cant_happen("raising numbers to a rational power not supported yet"); } else { // neither rational - res = int_power(left, right); + res = int_pow(left, right); protectValue(res); } LEAVE(ratPower); @@ -645,38 +727,12 @@ static Value ratNeg(Value v) { } void init_arithmetic() { - if (bigint_flag) { - int_add = bigAdd; - int_mul = bigMul; - int_sub = bigSub; - int_divide = bigDivide; - int_power = bigPower; - int_modulo = bigModulo; - int_gcd = bigGcd; - int_cmp = bigCmp; - int_neg_in_place = bigNegInPlace; - int_isneg = bigIsNeg; - int_neg = bigNeg; - BigInt *zero = bigIntFromInt(0); - Zero.type = VALUE_TYPE_BIGINT; - Zero.val = VALUE_VAL_BIGINT(zero); - BigInt *one = bigIntFromInt(1); - One.type = VALUE_TYPE_BIGINT; - One.val = VALUE_VAL_BIGINT(one); - } else { - int_add = littleAdd; - int_mul = littleMul; - int_sub = littleSub; - int_divide = littleDivide; - int_power = littlePower; - int_modulo = littleModulo; - int_gcd = littleGcd; - int_neg_in_place = littleNegInPlace; - int_neg = littleNeg; - int_isneg = littleIsNeg; - int_neg = littleNeg; - int_cmp = littleCmp; - } + BigInt *zero = bigIntFromInt(0); + Zero.type = VALUE_TYPE_BIGINT; + Zero.val = VALUE_VAL_BIGINT(zero); + BigInt *one = bigIntFromInt(1); + One.type = VALUE_TYPE_BIGINT; + One.val = VALUE_VAL_BIGINT(one); if (rational_flag) { nadd = ratAdd; @@ -691,9 +747,9 @@ void init_arithmetic() { nadd = int_add; nmul = int_mul; nsub = int_sub; - ndiv = int_divide; - npow = int_power; - nmod = int_modulo; + ndiv = int_div; + npow = int_pow; + nmod = int_mod; nneg = int_neg; ncmp = int_cmp; } diff --git a/src/arithmetic.h b/src/arithmetic.h index 9df9817..75c3ec9 100644 --- a/src/arithmetic.h +++ b/src/arithmetic.h @@ -19,8 +19,9 @@ */ #include "value.h" +#include "cmp.h" -typedef ValueCmp (*CmpBinOp)(Value, Value); +typedef Cmp (*CmpBinOp)(Value, Value); typedef Value (*IntegerBinOp)(Value, Value); typedef Value (*IntegerUnOp)(Value); typedef Value (*ParameterizedBinOp)(IntegerBinOp, Value, Value); diff --git a/src/ast.yaml b/src/ast.yaml index caa07b1..dd59edf 100644 --- a/src/ast.yaml +++ b/src/ast.yaml @@ -146,7 +146,7 @@ unions: named: AstNamedArg env: AstEnvType unpack: AstUnpack - number: BigInt + number: MaybeBigInt character: char tuple: AstArgList @@ -154,7 +154,7 @@ unions: back: void_ptr funCall: AstFunCall symbol: HashSymbol - number: BigInt + number: MaybeBigInt character: char fun: AstCompositeFunction env: AstEnv diff --git a/src/bigint.c b/src/bigint.c index 0ba7a3e..1c172de 100644 --- a/src/bigint.c +++ b/src/bigint.c @@ -1269,21 +1269,27 @@ double bigint_double(const bigint * src) { // additional CEKF code -// set true by main/getopts to enable bigint usage -int bigint_flag = 0; +MaybeBigInt *newMaybeBigInt(bigint bi) { + MaybeBigInt *x = NEW(MaybeBigInt, OBJTYPE_MAYBEBIGINT); + DEBUG("newMaybeBigInt %p", x); + x->little = 0; + x->fake = false; + x->bi = bi; + return x; +} BigInt *newBigInt(bigint bi) { BigInt *x = NEW(BigInt, OBJTYPE_BIGINT); DEBUG("newBigInt %p", x); - x->little = 0; x->bi = bi; return x; } -BigInt *fakeBigInt(int little) { - BigInt *x = NEW(BigInt, OBJTYPE_BIGINT); - DEBUG("newBigInt %p", x); +MaybeBigInt *fakeBigInt(int little) { + MaybeBigInt *x = NEW(MaybeBigInt, OBJTYPE_BIGINT); + DEBUG("fakeBigInt %p", x); x->little = little; + x->fake = true; bzero(&x->bi, sizeof(bigint)); return x; } @@ -1295,6 +1301,40 @@ BigInt *bigIntFromInt(int i) { return newBigInt(c); } +static BigInt *bigIntFromOperation(bigint_binop op, int a, int b) { + bigint c; + bigint_init(&c); + bigint_from_int(&c, a); + bigint d; + bigint_init(&d); + bigint_from_int(&d, b); + bigint e; + bigint_init(&e); + op(&e, &c, &d); + bigint_free(&c); + bigint_free(&d); + return newBigInt(e); +} + +BigInt *bigIntFromAddition(int a, int b) { + return bigIntFromOperation(bigint_add, a, b); +} + +BigInt *bigIntFromMultiplication(int a, int b) { + return bigIntFromOperation(bigint_mul, a, b); +} + +BigInt *bigIntFromPower(int a, int b) { + bigint c; + bigint_init(&c); + bigint_from_int(&c, a); + bigint d; + bigint_init(&d); + bigint_pow_word(&d, &c, b); + bigint_free(&c); + return newBigInt(d); +} + BigInt *copyBigInt(BigInt *b) { bigint bi; bigint_init(&bi); @@ -1308,14 +1348,27 @@ void markBigInt(BigInt *x) { MARK(x); } +void markMaybeBigInt(MaybeBigInt *x) { + if (x == NULL) + return; + MARK(x); +} + void freeBigInt(BigInt *x) { FREE_ARRAY(bigint_word, x->bi.words, x->bi.capacity); FREE(x, BigInt); } -void printBigInt(BigInt *x, int depth) { +void freeMaybeBigInt(MaybeBigInt *x) { + if (!x->fake) { + FREE_ARRAY(bigint_word, x->bi.words, x->bi.capacity); + } + FREE(x, MaybeBigInt); +} + +void printMaybeBigInt(MaybeBigInt *x, int depth) { eprintf("%*s", depth * PAD_WIDTH, ""); - fprintBigInt(errout, x); + fprintMaybeBigInt(errout, x); } void bigint_fprint(FILE *f, bigint * bi) { @@ -1337,30 +1390,62 @@ void fprintBigInt(FILE *f, BigInt *x) { fprintf(f, ""); return; } - if (bigint_flag) { - bigint_fprint(f, &x->bi); - } else { - fprintf(f, "%d", x->little); - } + bigint_fprint(f, &x->bi); } -void sprintBigInt(char *s, BigInt *x) { +void fprintMaybeBigInt(FILE *f, MaybeBigInt *x) { if (x == NULL) { - sprintf(s, ""); + fprintf(f, ""); return; } - if (bigint_flag) { - int size = bigint_write_size(&x->bi, 10); - bigint_write(s, size, &x->bi); + if (x->fake) { + fprintf(f, "%d", x->little); } else { - sprintf(s, "%d", x->little); + bigint_fprint(f, &x->bi); } } -int cmpBigInt(BigInt *a, BigInt *b) { - if (bigint_flag) - return bigint_cmp(&a->bi, &b->bi); - return a->little < b->little ? -1 : a->little == b->little ? 0 : 1; +Cmp cmpBigInt(BigInt *a, BigInt *b) { + return (Cmp) bigint_cmp(&a->bi, &b->bi); +} + +Cmp cmpBigIntInt(BigInt *a, int b) { + bigint bi; + bigint_init(&bi); + bigint_from_int(&bi, b); + Cmp res = (Cmp) bigint_cmp(&a->bi, &bi); + bigint_free(&bi); + return res; +} + +Cmp cmpMaybeBigInt(MaybeBigInt *x, MaybeBigInt *y) { + if (x->fake) { + if (y->fake) { + return x->little < y->little ? + -1 : + x->little == y->little ? + 0 : + 1; + } else { + bigint bx; + bigint_init(&bx); + bigint_from_int(&bx, x->little); + Cmp res = (Cmp) bigint_cmp(&bx, &y->bi); + bigint_free(&bx); + return res; + } + } else { + if (y->fake) { + bigint by; + bigint_init(&by); + bigint_from_int(&by, y->little); + Cmp res = (Cmp) bigint_cmp(&x->bi, &by); + bigint_free(&by); + return res; + } else { + return (Cmp) bigint_cmp(&x->bi, &y->bi); + } + } } static BigInt *_opBigInt(bigint_binop op, BigInt *a, BigInt *b) { @@ -1374,30 +1459,94 @@ static BigInt *_opBigInt(bigint_binop op, BigInt *a, BigInt *b) { return res; } +static BigInt *_opBigIntInt(bigint_binop op, BigInt *a, int i) { + int save = PROTECT(a); + bigint b; + bigint_init(&b); + bigint_from_int(&b, i); + bigint c; + bigint_init(&c); + op(&c, &a->bi, &b); + bigint_free(&b); + BigInt *res = newBigInt(c); + UNPROTECT(save); + return res; +} + +static BigInt *_opIntBigInt(bigint_binop op, int i, BigInt *a) { + int save = PROTECT(a); + bigint b; + bigint_init(&b); + bigint_from_int(&b, i); + bigint c; + bigint_init(&c); + op(&c, &b, &a->bi); + bigint_free(&b); + BigInt *res = newBigInt(c); + UNPROTECT(save); + return res; +} + BigInt *addBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_add, a, b); } +BigInt *addBigIntInt(BigInt *a, int b) { + return _opBigIntInt(bigint_add, a, b); +} + BigInt *subBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_sub, a, b); } +BigInt *subIntBigInt(int a, BigInt *b) { + return _opIntBigInt(bigint_sub, a, b); +} + BigInt *mulBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_mul, a, b); } +BigInt *mulBigIntInt(BigInt *a, int b) { + return _opBigIntInt(bigint_mul, a, b); +} + BigInt *divBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_div, a, b); } +BigInt *divBigIntInt(BigInt *a, int b) { + return _opBigIntInt(bigint_div, a, b); +} + +BigInt *divIntBigInt(int a, BigInt *b) { + return _opIntBigInt(bigint_div, a, b); +} + BigInt *modBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_mod, a, b); } +BigInt *modIntBigInt(int a, BigInt *b) { + return _opIntBigInt(bigint_mod, a, b); +} + +BigInt *modBigIntInt(BigInt *a, int b) { + return _opBigIntInt(bigint_mod, a, b); +} + BigInt *gcdBigInt(BigInt *a, BigInt *b) { return _opBigInt(bigint_gcd, a, b); } +BigInt *gcdBigIntInt(BigInt *a, int b) { + return _opBigIntInt(bigint_gcd, a, b); +} + +BigInt *gcdIntBigInt(int a, BigInt *b) { + return _opIntBigInt(bigint_gcd, a, b); +} + BigInt *powBigInt(BigInt *a, BigInt *b) { int save = PROTECT(a); PROTECT(b); @@ -1412,34 +1561,37 @@ BigInt *powBigInt(BigInt *a, BigInt *b) { return res; } -void dumpBigInt(FILE *fp, BigInt *big) { - fprintf(fp, "BigInt %p", big); - if (big != NULL) { - fprintf(fp, " size:%d, capacity:%d, neg:%d, words:[", big->bi.size, - big->bi.capacity, big->bi.neg); - for (int i = 0; i < big->bi.capacity;) { - fprintf(fp, "%d", big->bi.words[i]); - i++; - if (i < big->bi.capacity) - eprintf(", "); - } - fprintf(fp, "]"); +BigInt *powBigIntInt(BigInt *a, int b) { + int save = PROTECT(a); + bigint c; + bigint_init(&c); + bigint_pow_word(&c, &a->bi, b); + BigInt *res = newBigInt(c); + UNPROTECT(save); + return res; +} + +BigInt *powIntBigInt(int a, BigInt *b) { + int save = PROTECT(b); + if (b->bi.size > 1) { + cant_happen("maximum exponent for bigint exceeded"); } - fprintf(fp, "\n"); + bigint c; + bigint_init(&c); + bigint bigA; + bigint_init(&bigA); + bigint_from_int(&bigA, a); + bigint_pow_word(&c, &bigA, b->bi.words[0]); + bigint_free(&bigA); + BigInt *res = newBigInt(c); + UNPROTECT(save); + return res; } void negateBigInt(BigInt *b) { - if (bigint_flag) { - bigint_negate(&b->bi); - } else { - b->little = -b->little; - } + bigint_negate(&b->bi); } bool isNegBigInt(BigInt *b) { - if (bigint_flag) { - return b->bi.neg != 0; - } else { - return b->little < 0; - } + return b->bi.neg != 0; } diff --git a/src/bigint.h b/src/bigint.h index 7fa4478..0d35b5a 100644 --- a/src/bigint.h +++ b/src/bigint.h @@ -10,6 +10,7 @@ extern "C" { # include # include # include "memory.h" +# include "cmp.h" /* any unsigned integer type */ typedef uint32_t bigint_word; @@ -34,40 +35,67 @@ extern "C" { for (_i = 0; _i < (n)/2; _i++) BIGINT_SWAP(type, data[_i], data[n - 1 - _i]);\ } while (0) - extern int bigint_flag; - typedef struct bigint { bigint_word *words; int neg, size, capacity; } bigint; // CEKF wrapper for memory management - typedef struct BigInt { + // compile-time bigint + typedef struct MaybeBigInt { Header header; bigint bi; + bool fake; int little; + } MaybeBigInt; + + // run-time bigint + typedef struct BigInt { + Header header; + bigint bi; } BigInt; BigInt *newBigInt(bigint bi); - BigInt *fakeBigInt(int little); + MaybeBigInt *newMaybeBigInt(bigint bi); + MaybeBigInt *fakeBigInt(int little); BigInt *bigIntFromInt(int c); + BigInt *bigIntFromAddition(int a, int b); + BigInt *bigIntFromMultiplication(int a, int b); + BigInt *bigIntFromPower(int a, int b); + static inline BigInt *bigIntFromSubtraction(int a, int b) { return bigIntFromAddition(a, -b); } BigInt *copyBigInt(BigInt *b); void markBigInt(BigInt *b); + void markMaybeBigInt(MaybeBigInt *b); void freeBigInt(BigInt *b); - void printBigInt(BigInt *b, int depth); + void freeMaybeBigInt(MaybeBigInt *b); + void printMaybeBigInt(MaybeBigInt *b, int depth); void fprintBigInt(FILE *f, BigInt *x); - void sprintBigInt(char *s, BigInt *x); - int cmpBigInt(BigInt *a, BigInt *b); - void dumpBigInt(FILE *fp, BigInt *b); + void fprintMaybeBigInt(FILE *f, MaybeBigInt *x); + Cmp cmpBigInt(BigInt *a, BigInt *b); + Cmp cmpBigIntInt(BigInt *a, int b); + static inline Cmp cmpIntBigInt(int a, BigInt *b) { return (Cmp)(cmpBigIntInt(b, a) * -1); } + int cmpMaybeBigInt(MaybeBigInt *a, MaybeBigInt *b); typedef bigint *(*bigint_binop)(bigint * dst, const bigint * a, const bigint * b); BigInt *addBigInt(BigInt *a, BigInt *b); + BigInt *addBigIntInt(BigInt *a, int b); BigInt *subBigInt(BigInt *a, BigInt *b); + BigInt *subIntBigInt(int a, BigInt *b); + static inline BigInt *subBigIntInt(BigInt *a, int b) { return addBigIntInt(a, -b); } BigInt *mulBigInt(BigInt *a, BigInt *b); + BigInt *mulBigIntInt(BigInt *a, int b); BigInt *divBigInt(BigInt *a, BigInt *b); + BigInt *divBigIntInt(BigInt *a, int b); + BigInt *divIntBigInt(int a, BigInt *b); BigInt *modBigInt(BigInt *a, BigInt *b); + BigInt *modBigIntInt(BigInt *a, int b); + BigInt *modIntBigInt(int a, BigInt *b); BigInt *powBigInt(BigInt *a, BigInt *b); + BigInt *powBigIntInt(BigInt *a, int b); + BigInt *powIntBigInt(int a, BigInt *b); BigInt *gcdBigInt(BigInt *a, BigInt *b); + BigInt *gcdBigIntInt(BigInt *a, int b); + BigInt *gcdIntBigInt(int a, BigInt *b); void bigint_fprint(FILE *f, bigint * bi); void negateBigInt(BigInt *b); bool isNegBigInt(BigInt *b); diff --git a/src/bytecode.c b/src/bytecode.c index b8333b1..f7f4fe3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -379,10 +379,12 @@ void writeCexpIntCond(CexpIntCondCases *x, ByteCodeArray *b) { for (CexpIntCondCases *xx = x; xx != NULL; xx = xx->next) { if (xx->next == NULL) break; // default case doesn't get a test - if (bigint_flag) { - addBig(b, xx->option->bi); - } else { + if (xx->option->fake) { + addByte(b, BYTECODE_STDINT); addInt(b, xx->option->little); + } else { + addByte(b, BYTECODE_BIGINT); + addBig(b, xx->option->bi); } dispatches[i++] = reserveWord(b); } @@ -558,12 +560,12 @@ void writeAexp(Aexp *x, ByteCodeArray *b) { } break; case AEXP_TYPE_BIGINTEGER:{ - if (bigint_flag) { - addByte(b, BYTECODE_BIGINT); - addBig(b, x->val.biginteger->bi); - } else { + if (x->val.biginteger->fake) { addByte(b, BYTECODE_STDINT); addInt(b, x->val.biginteger->little); + } else { + addByte(b, BYTECODE_BIGINT); + addBig(b, x->val.biginteger->bi); } } break; diff --git a/src/common.h b/src/common.h index 83966c7..f81a1a2 100644 --- a/src/common.h +++ b/src/common.h @@ -29,6 +29,7 @@ // # define DEBUG_STEP // if DEBUG_STEP is defined, this sleeps for 1 second between each machine step // # define DEBUG_SLOW_STEP +// # define DEBUG_BYTECODE // define this to cause a GC at every malloc (catches memory leaks early) # define DEBUG_STRESS_GC // # define DEBUG_LOG_GC @@ -43,7 +44,6 @@ // # define DEBUG_TIN_SUBSTITUTION // # define DEBUG_TIN_INSTANTIATION // # define DEBUG_TIN_UNIFICATION -// # define DEBUG_BYTECODE // define this to make fatal errors dump core (if ulimit allows) # define DEBUG_DUMP_CORE // # define DEBUG_TC diff --git a/src/debug.c b/src/debug.c index cbc8141..5cf4578 100644 --- a/src/debug.c +++ b/src/debug.c @@ -468,14 +468,22 @@ void dumpByteCode(ByteCodeArray *bca) { int count = readWord(bca, &i); eprintf("INTCOND [%d]", count); while (count > 0) { - if (bigint_flag) { - bigint bi = readBigint(bca, &i); - eprintf(" "); - bigint_fprint(errout, &bi); - bigint_free(&bi); - } else { - int li = readInt(bca, &i); - eprintf(" %d", li); + int type = readByte(bca, &i); + switch (type) { + case BYTECODE_BIGINT: { + bigint bi = readBigint(bca, &i); + eprintf(" [bigint]"); + bigint_fprint(errout, &bi); + bigint_free(&bi); + } + break; + case BYTECODE_STDINT: { + int li = readInt(bca, &i); + eprintf(" [int]%d", li); + } + break; + default: + cant_happen("expected INT or BIGINT in BYTECODE_INTCOND cases"); } int offset = readOffset(bca, &i); eprintf(":[%04x]", offset); diff --git a/src/lambda.yaml b/src/lambda.yaml index 7a9b7f6..aeaeb73 100644 --- a/src/lambda.yaml +++ b/src/lambda.yaml @@ -90,7 +90,7 @@ structs: cases: LamCondCases LamIntCondCases: - constant: BigInt + constant: MaybeBigInt body: LamExp next: LamIntCondCases @@ -226,7 +226,7 @@ unions: lam: LamLam var: HashSymbol stdint: int - biginteger: BigInt + biginteger: MaybeBigInt prim: LamPrimApp unary: LamUnaryApp list: LamSequence diff --git a/src/lambda_pp.c b/src/lambda_pp.c index 3c18daf..58bf664 100644 --- a/src/lambda_pp.c +++ b/src/lambda_pp.c @@ -110,7 +110,7 @@ void ppLamExp(LamExp *exp) { ppHashSymbol(exp->val.var); break; case LAMEXP_TYPE_BIGINTEGER: - fprintBigInt(errout, exp->val.biginteger); + fprintMaybeBigInt(errout, exp->val.biginteger); break; case LAMEXP_TYPE_STDINT: eprintf("%d", exp->val.stdint); @@ -370,7 +370,7 @@ void ppLamIff(LamIff *iff) { static void _ppLamIntCondCases(LamIntCondCases *cases) { eprintf("("); - fprintBigInt(errout, cases->constant); + fprintMaybeBigInt(errout, cases->constant); eprintf(" "); ppLamExp(cases->body); eprintf(")"); diff --git a/src/main.c b/src/main.c index d1e8429..8747424 100644 --- a/src/main.c +++ b/src/main.c @@ -54,7 +54,6 @@ static void processArgs(int argc, char *argv[]) { while (1) { static struct option long_options[] = { - { "bigint", no_argument, &bigint_flag, 1 }, { "rational", no_argument, &rational_flag, 1 }, { "report", no_argument, &report_flag, 1 }, { "anf", no_argument, &anf_flag, 1 }, @@ -82,7 +81,6 @@ static void processArgs(int argc, char *argv[]) { if (help_flag) { printf("%s", - "--bigint use arbitrary precision integers\n" "--rational use precision-preserving rational numbers\n" "--report report statistics\n" "--anf display the generated ANF\n" diff --git a/src/memory.c b/src/memory.c index 7608f2c..b4ea136 100644 --- a/src/memory.c +++ b/src/memory.c @@ -331,6 +331,9 @@ void freeObj(Header *h) { case OBJTYPE_BIGINT: freeBigInt((BigInt *) h); break; + case OBJTYPE_MAYBEBIGINT: + freeMaybeBigInt((MaybeBigInt *) h); + break; case OBJTYPE_HASHTABLE: freeHashTableObj(h); break; diff --git a/src/memory.h b/src/memory.h index ebc5996..00b1d90 100644 --- a/src/memory.h +++ b/src/memory.h @@ -45,6 +45,7 @@ typedef enum { OBJTYPE_PROTECTION, OBJTYPE_BIGINT, + OBJTYPE_MAYBEBIGINT, OBJTYPE_PMMODULE, ANF_OBJTYPES(), diff --git a/src/parser.y b/src/parser.y index 3e78187..2168b11 100644 --- a/src/parser.y +++ b/src/parser.y @@ -80,16 +80,65 @@ static AstUnpack *newStringUnpack(AstCharArray *str) { return res; } -static BigInt *makeBigInt(char *digits) { - if (bigint_flag) { - bigint bi; - bigint_init(&bi); - bigint_from_str(&bi, digits); - BigInt *bbi = newBigInt(bi); +static void bigint_mul_by_ten(bigint *b) { + bigint old; + bigint_init(&old); + bigint_cpy(&old, b); + bigint_free(b); + bigint_init(b); + bigint ten; + bigint_init(&ten); + bigint_from_int(&ten, 10); + bigint_mul(b, &ten, &old); + bigint_free(&ten); + bigint_free(&old); +} + +static void bigint_add_n(bigint *b, int n) { + bigint old; + bigint_init(&old); + bigint_cpy(&old, b); + bigint_free(b); + bigint_init(b); + bigint_add_word(b, &old, n); + bigint_free(&old); +} + +static MaybeBigInt *makeMaybeBigInt(char *digits) { + bool overflowed = false; + int a = 0; + bigint bi; + for (char *p = digits; *p != '\0'; ++p) { + int n = *p - '0'; + if(overflowed) { + bigint_mul_by_ten(&bi); + bigint_add_n(&bi, n); + } else { + int c; + if (__builtin_mul_overflow(a, 10, &c)) { + overflowed = true; + bigint_init(&bi); + bigint_from_int(&bi, a); + bigint_mul_by_ten(&bi); + bigint_add_n(&bi, n); + } else { + a = c; + if (__builtin_add_overflow(a, n, &c)) { + overflowed = true; + bigint_init(&bi); + bigint_from_int(&bi, a); + bigint_add_n(&bi, n); + } else { + a = c; + } + } + } + } + if (overflowed) { + MaybeBigInt *bbi = newMaybeBigInt(bi); return bbi; } else { - int i = atoi(digits); - return fakeBigInt(i); + return fakeBigInt(a); } } @@ -123,7 +172,7 @@ static AstCompositeFunction *makeAstCompositeFunction(AstAltFunction *functions, %union { char *s; char c; - BigInt *bi; + MaybeBigInt *bi; AstArg *arg; AstArgList *argList; AstCompositeFunction *compositeFunction; @@ -360,7 +409,7 @@ consfargs : farg { $$ = newAstUnpack(consSymbol(), newAstArgList( | farg ',' consfargs { $$ = newAstUnpack(consSymbol(), newAstArgList($1, newAstArgList(newAstArg(AST_ARG_TYPE_UNPACK, AST_ARG_VAL_UNPACK($3)), NULL))); } ; -number : NUMBER { $$ = makeBigInt($1); } +number : NUMBER { $$ = makeMaybeBigInt($1); } ; farg : symbol { $$ = newAstArg(AST_ARG_TYPE_SYMBOL, AST_ARG_VAL_SYMBOL($1)); } diff --git a/src/primitives.yaml b/src/primitives.yaml index bbb4656..3be5198 100644 --- a/src/primitives.yaml +++ b/src/primitives.yaml @@ -50,6 +50,13 @@ BigInt: compareFn: "cmpBigInt" valued: true +MaybeBigInt: + cname: "MaybeBigInt *" + printFn: "printMaybeBigInt" + markFn: "markMaybeBigInt" + compareFn: "cmpMaybeBigInt" + valued: true + string: cname: "char *" printf: "%s" diff --git a/src/step.c b/src/step.c index e6780ee..e73aa9f 100644 --- a/src/step.c +++ b/src/step.c @@ -135,9 +135,9 @@ static bool truthy(Value v) { || v.type == VALUE_TYPE_VOID); } -static ValueCmp _cmp(Value left, Value right); +static Cmp _cmp(Value left, Value right); -static ValueCmp _vecCmp(Vec *left, Vec *right) { +static Cmp _vecCmp(Vec *left, Vec *right) { if (left == right) { return 0; } @@ -151,15 +151,15 @@ static ValueCmp _vecCmp(Vec *left, Vec *right) { #endif for (int i = 0; i < left->size; ++i) { int cmp = _cmp(left->values[i], right->values[i]); - if (cmp != VALUE_CMP_EQ) + if (cmp != CMP_EQ) return cmp; } - return VALUE_CMP_EQ; + return CMP_EQ; } -#define _CMP_(left, right) ((left) < (right) ? VALUE_CMP_LT : (left) == (right) ? VALUE_CMP_EQ : VALUE_CMP_GT) +#define _CMP_(left, right) ((left) < (right) ? CMP_LT : (left) == (right) ? CMP_EQ : CMP_GT) -static ValueCmp _cmp(Value left, Value right) { +static Cmp _cmp(Value left, Value right) { #ifdef DEBUG_STEP eprintf("_cmp:\n"); printContainedValue(left, 0); @@ -210,11 +210,11 @@ static ValueCmp _cmp(Value left, Value right) { static Value vcmp(Value left, Value right) { switch (_cmp(left, right)) { - case VALUE_CMP_LT: + case CMP_LT: return vLt; - case VALUE_CMP_EQ: + case CMP_EQ: return vEq; - case VALUE_CMP_GT: + case CMP_GT: return vGt; default: cant_happen("unexpected value from _cmp"); @@ -222,15 +222,15 @@ static Value vcmp(Value left, Value right) { } static bool _eq(Value left, Value right) { - return _cmp(left, right) == VALUE_CMP_EQ; + return _cmp(left, right) == CMP_EQ; } static bool _gt(Value left, Value right) { - return _cmp(left, right) == VALUE_CMP_GT; + return _cmp(left, right) == CMP_GT; } static bool _lt(Value left, Value right) { - return _cmp(left, right) == VALUE_CMP_LT; + return _cmp(left, right) == CMP_LT; } static bool _xor(Value left, Value right) { @@ -396,6 +396,7 @@ static int count = 0; void reportSteps(void) { printf("%d instructions executed\n", count); + printf("%d final stack capacity\n", state.S.capacity); } static void step() { @@ -517,7 +518,9 @@ static void step() { int save = protectValue(right); Value left = pop(); protectValue(left); - push(nsub(left, right)); + Value res = nsub(left, right); + protectValue(res); + push(res); UNPROTECT(save); } break; @@ -738,12 +741,19 @@ static void step() { int here = state.C; for (int ip = 0; ip < size; ip++) { printf(" "); - if (bigint_flag) { - BigInt *bigInt = readCurrentBigInt(); - fprintBigInt(stdout, bigInt); - } else { - int Int = readCurrentInt(); - printf("%d", Int); + switch(readCurrentByte()) { + case BYTECODE_BIGINT: { + BigInt *bigInt = readCurrentBigInt(); + fprintBigInt(stdout, bigInt); + } + break; + case BYTECODE_STDINT: { + int Int = readCurrentInt(); + printf("%d", Int); + } + break; + default: + cant_happen("expected int or bigint in INTCOND cases"); } int offset = readCurrentOffset(); printf(":[%04x]", offset); @@ -753,25 +763,40 @@ static void step() { #endif Value v = pop(); int save = protectValue(v); - if (bigint_flag) { - for (int ip = 0; ip < size; ip++) { - BigInt *bigInt = readCurrentBigInt(); - int offset = readCurrentOffset(); - if (cmpBigInt(bigInt, v.val.bigint) == 0) { - state.C = offset; - break; + for (int ip = 0; ip < size; ip++) { + switch(readCurrentByte()) { + case BYTECODE_BIGINT: { + BigInt *bigInt = readCurrentBigInt(); + PROTECT(bigInt); + Value u; + u.type = VALUE_TYPE_BIGINT; + u.val = VALUE_VAL_BIGINT(bigInt); + protectValue(u); + int offset = readCurrentOffset(); + if (ncmp(u, v) == CMP_EQ) { + state.C = offset; + goto FINISHED_INTCOND; + } } - } - } else { - for (int ip = 0; ip < size; ip++) { - int option = readCurrentInt(); - int offset = readCurrentOffset(); - if (option == v.val.stdint) { - state.C = offset; - break; + break; + case BYTECODE_STDINT: { + int option = readCurrentInt(); + Value u; + u.type = VALUE_TYPE_STDINT; + u.val = VALUE_VAL_STDINT(option); + protectValue(u); + int offset = readCurrentOffset(); + if (ncmp(u, v) == CMP_EQ) { + state.C = offset; + goto FINISHED_INTCOND; + } } + break; + default: + cant_happen("expected int or bigint in INTCOND cases"); } } + FINISHED_INTCOND: UNPROTECT(save); } break; diff --git a/src/tpmc.yaml b/src/tpmc.yaml index b684bcb..ad320a9 100644 --- a/src/tpmc.yaml +++ b/src/tpmc.yaml @@ -94,7 +94,7 @@ unions: assignment: TpmcAssignmentPattern wildcard: void_ptr character: char - biginteger: BigInt + biginteger: MaybeBigInt constructor: TpmcConstructorPattern tuple: TpmcPatternArray diff --git a/src/tpmc_compare.c b/src/tpmc_compare.c index 0566a19..cd30982 100644 --- a/src/tpmc_compare.c +++ b/src/tpmc_compare.c @@ -123,7 +123,7 @@ bool tpmcPatternValueEq(TpmcPatternValue *a, TpmcPatternValue *b) { case TPMCPATTERNVALUE_TYPE_CHARACTER: return a->val.character == b->val.character; case TPMCPATTERNVALUE_TYPE_BIGINTEGER: - return cmpBigInt(a->val.biginteger, b->val.biginteger) == 0; + return cmpMaybeBigInt(a->val.biginteger, b->val.biginteger) == 0; case TPMCPATTERNVALUE_TYPE_CONSTRUCTOR: return tpmcConstructorPatternEq(a->val.constructor, b->val.constructor); diff --git a/src/tpmc_logic.c b/src/tpmc_logic.c index a268842..862eb17 100644 --- a/src/tpmc_logic.c +++ b/src/tpmc_logic.c @@ -153,7 +153,7 @@ static TpmcPattern *makeTuplePattern(AstArgList *args, LamContext *env) { return pattern; } -static TpmcPattern *makeBigIntegerPattern(BigInt *number) { +static TpmcPattern *makeMaybeBigIntegerPattern(MaybeBigInt *number) { TpmcPatternValue *val = newTpmcPatternValue(TPMCPATTERNVALUE_TYPE_BIGINTEGER, TPMCPATTERNVALUE_VAL_BIGINTEGER(number)); @@ -188,7 +188,7 @@ static TpmcPattern *convertPattern(AstArg *arg, LamContext *env) { case AST_ARG_TYPE_TUPLE: return makeTuplePattern(arg->val.tuple, env); case AST_ARG_TYPE_NUMBER: - return makeBigIntegerPattern(arg->val.number); + return makeMaybeBigIntegerPattern(arg->val.number); case AST_ARG_TYPE_CHARACTER: return makeCharacterPattern(arg->val.character); default: diff --git a/src/tpmc_match.c b/src/tpmc_match.c index 72c250d..c0af56a 100644 --- a/src/tpmc_match.c +++ b/src/tpmc_match.c @@ -124,7 +124,7 @@ static bool patternMatches(TpmcPattern *constructor, TpmcPattern *pattern) { bool res = isComparison || (constructor->pattern->type == TPMCPATTERNVALUE_TYPE_BIGINTEGER - && cmpBigInt(constructor->pattern->val.biginteger, + && cmpMaybeBigInt(constructor->pattern->val.biginteger, pattern->pattern->val.biginteger) == 0); return res; } diff --git a/src/tpmc_mermaid.c b/src/tpmc_mermaid.c index 2c642ea..87890a3 100644 --- a/src/tpmc_mermaid.c +++ b/src/tpmc_mermaid.c @@ -128,7 +128,7 @@ static void mermaidPattern(TpmcPattern *pattern) { printf("'%c'", value->val.character); break; case TPMCPATTERNVALUE_TYPE_BIGINTEGER: - fprintBigInt(stdout, value->val.biginteger); + fprintMaybeBigInt(stdout, value->val.biginteger); break; case TPMCPATTERNVALUE_TYPE_CONSTRUCTOR: printf("%s(", value->val.constructor->tag->name); diff --git a/src/tpmc_pp.c b/src/tpmc_pp.c index ef01313..27286f4 100644 --- a/src/tpmc_pp.c +++ b/src/tpmc_pp.c @@ -76,7 +76,7 @@ void ppTpmcPatternValue(TpmcPatternValue *patternValue) { eprintf("'%c'", patternValue->val.character); break; case TPMCPATTERNVALUE_TYPE_BIGINTEGER: - fprintBigInt(errout, patternValue->val.biginteger); + fprintMaybeBigInt(errout, patternValue->val.biginteger); break; case TPMCPATTERNVALUE_TYPE_TUPLE: ppTpmcTuplePattern(patternValue->val.tuple); diff --git a/src/tpmc_translate.c b/src/tpmc_translate.c index b47ae30..439849e 100644 --- a/src/tpmc_translate.c +++ b/src/tpmc_translate.c @@ -483,7 +483,7 @@ static LamExp *translateArcList(TpmcArcList *arcList, LamExp *testVar, } static LamIntCondCases *makeConstantIntCondCase(TpmcArcList *arcList, - BigInt *constant, + MaybeBigInt *constant, LamExp *testVar, LamExpTable *lambdaCache) { LamIntCondCases *next = @@ -546,7 +546,7 @@ static LamIntCondCases *translateConstantIntArcList(TpmcArcList *arcList, ("encountered character case when cinstructing an integer cond"); } case TPMCPATTERNVALUE_TYPE_BIGINTEGER:{ - BigInt *integer = arcList->arc->test->pattern->val.biginteger; + MaybeBigInt *integer = arcList->arc->test->pattern->val.biginteger; res = makeConstantIntCondCase(arcList, integer, testVar, lambdaCache); diff --git a/src/value.h b/src/value.h index 8f2c5d6..83adb4c 100644 --- a/src/value.h +++ b/src/value.h @@ -20,12 +20,6 @@ # include "bigint.h" -typedef enum { - VALUE_CMP_LT = -1, - VALUE_CMP_EQ = 0, - VALUE_CMP_GT = 1 -} ValueCmp; - typedef enum { VALUE_TYPE_VOID, VALUE_TYPE_STDINT, From f3821e4bb8575baddb787baf4808f6d955cb0fb1 Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sun, 7 Apr 2024 16:27:46 +0100 Subject: [PATCH 5/7] rationals no longer optional --- src/arithmetic.c | 81 ++++++++++++++++-------------------------------- src/arithmetic.h | 25 +++++---------- src/main.c | 2 -- 3 files changed, 35 insertions(+), 73 deletions(-) diff --git a/src/arithmetic.c b/src/arithmetic.c index bd8c996..43e0813 100644 --- a/src/arithmetic.c +++ b/src/arithmetic.c @@ -34,16 +34,10 @@ #define NUMERATOR 0 #define DENOMINATOR 1 -int rational_flag = 0; +typedef Value (*IntegerBinOp)(Value, Value); +typedef Value (*ParameterizedBinOp)(IntegerBinOp, Value, Value); -IntegerBinOp nadd; -IntegerBinOp nsub; -IntegerBinOp nmul; -IntegerBinOp ndiv; -IntegerBinOp npow; -IntegerBinOp nmod; -IntegerUnOp nneg; -CmpBinOp ncmp; +int rational_flag = 0; static Value One = { .type = VALUE_TYPE_STDINT, @@ -457,8 +451,8 @@ static Value makeRational(Value numerator, Value denominator) { return res; } -static Cmp ratCmp(Value left, Value right) { - ENTER(ratCmp); +Cmp ncmp(Value left, Value right) { + ENTER(ncmp); Cmp res; int save = PROTECT(NULL); if (left.type == VALUE_TYPE_RATIONAL) { @@ -478,7 +472,7 @@ static Cmp ratCmp(Value left, Value right) { res = int_cmp(left, right); } } - LEAVE(ratCmp); + LEAVE(ncmp); UNPROTECT(save); return res; } @@ -581,19 +575,19 @@ static Value _rat_add_sub(IntegerBinOp base_op, Value left, Value right) { return res; } -static Value ratAdd(Value left, Value right) { - ENTER(ratAdd); +Value nadd(Value left, Value right) { + ENTER(nadd); IFDEBUG(ppNumber(left)); IFDEBUG(ppNumber(right)); Value res = ratOp(left, right, _rat_add_sub, int_add, true); - LEAVE(ratAdd); + LEAVE(nadd); return res; } -static Value ratSub(Value left, Value right) { - ENTER(ratSub); +Value nsub(Value left, Value right) { + ENTER(nsub); Value res = ratOp(left, right, _rat_add_sub, int_sub, true); - LEAVE(ratSub); + LEAVE(nsub); return res; } @@ -619,13 +613,13 @@ static Value _rat_mul(IntegerBinOp base_op, Value left, Value right) { return res; } -static Value ratMul(Value left, Value right) { - ENTER(ratMul); +Value nmul(Value left, Value right) { + ENTER(nmul); IFDEBUG(ppNumber(left)); IFDEBUG(ppNumber(right)); Value res = ratOp(left, right, _rat_mul, int_mul, true); int save = protectValue(res); - LEAVE(ratMul); + LEAVE(nmul); IFDEBUG(ppNumber(res)); UNPROTECT(save); return res; @@ -647,21 +641,21 @@ static Value _rat_div(IntegerBinOp base_op, Value left, Value right) { return res; } -static Value ratDivide(Value left, Value right) { - ENTER(ratDivide); +Value ndiv(Value left, Value right) { + ENTER(ndiv); // N.B. int_mul not int_div Value res = ratOp(left, right, _rat_div, int_mul, false); int save = protectValue(res); - LEAVE(ratDivide); + LEAVE(ndiv); IFDEBUG(ppNumber(res)); UNPROTECT(save); return res; } -static Value ratModulo(Value left, Value right) { - ENTER(ratModulo); +Value nmod(Value left, Value right) { + ENTER(nmod); Value res = ratOp(left, right, _rat_add_sub, int_mod, true); - LEAVE(ratModulo); + LEAVE(nmod); return res; } @@ -682,9 +676,8 @@ static Value _ratPower(Value left, Value right) { return res; } -static Value ratPower(Value left, Value right) { - ENTER(ratPower); - LEAVE(ratPower); +Value npow(Value left, Value right) { + ENTER(npow); IFDEBUG(ppNumber(left)); IFDEBUG(ppNumber(right)); Value res; @@ -705,14 +698,14 @@ static Value ratPower(Value left, Value right) { res = int_pow(left, right); protectValue(res); } - LEAVE(ratPower); + LEAVE(npow); IFDEBUG(ppNumber(res)); UNPROTECT(save); return res; } -static Value ratNeg(Value v) { - ENTER(ratNeg); +Value nneg(Value v) { + ENTER(nneg); Value res; if (v.type == VALUE_TYPE_RATIONAL) { Value numerator = int_neg(v.val.vec->values[NUMERATOR]); @@ -722,7 +715,7 @@ static Value ratNeg(Value v) { } else { res = int_neg(v); } - LEAVE(ratNeg); + LEAVE(nneg); return res; } @@ -733,26 +726,6 @@ void init_arithmetic() { BigInt *one = bigIntFromInt(1); One.type = VALUE_TYPE_BIGINT; One.val = VALUE_VAL_BIGINT(one); - - if (rational_flag) { - nadd = ratAdd; - nsub = ratSub; - nmul = ratMul; - ndiv = ratDivide; - npow = ratPower; - nmod = ratModulo; - nneg = ratNeg; - ncmp = ratCmp; - } else { - nadd = int_add; - nmul = int_mul; - nsub = int_sub; - ndiv = int_div; - npow = int_pow; - nmod = int_mod; - nneg = int_neg; - ncmp = int_cmp; - } } void markArithmetic() { diff --git a/src/arithmetic.h b/src/arithmetic.h index 75c3ec9..0a6b045 100644 --- a/src/arithmetic.h +++ b/src/arithmetic.h @@ -21,23 +21,14 @@ #include "value.h" #include "cmp.h" -typedef Cmp (*CmpBinOp)(Value, Value); -typedef Value (*IntegerBinOp)(Value, Value); -typedef Value (*IntegerUnOp)(Value); -typedef Value (*ParameterizedBinOp)(IntegerBinOp, Value, Value); -typedef void (*voidOp)(Value *); -typedef bool (*boolOp)(Value); - -extern int rational_flag; - -extern IntegerBinOp nadd; -extern IntegerBinOp nsub; -extern IntegerBinOp nmul; -extern IntegerBinOp ndiv; -extern IntegerBinOp npow; -extern IntegerBinOp nmod; -extern IntegerUnOp nneg; -extern CmpBinOp ncmp; +Value nadd(Value, Value); +Value nsub(Value, Value); +Value nmul(Value, Value); +Value ndiv(Value, Value); +Value npow(Value, Value); +Value nmod(Value, Value); +Value nneg(Value); +Cmp ncmp(Value, Value); void init_arithmetic(void); void markArithmetic(void); diff --git a/src/main.c b/src/main.c index 8747424..b65a895 100644 --- a/src/main.c +++ b/src/main.c @@ -54,7 +54,6 @@ static void processArgs(int argc, char *argv[]) { while (1) { static struct option long_options[] = { - { "rational", no_argument, &rational_flag, 1 }, { "report", no_argument, &report_flag, 1 }, { "anf", no_argument, &anf_flag, 1 }, { "dump-bytecode", no_argument, &dump_bytecode_flag, 1 }, @@ -81,7 +80,6 @@ static void processArgs(int argc, char *argv[]) { if (help_flag) { printf("%s", - "--rational use precision-preserving rational numbers\n" "--report report statistics\n" "--anf display the generated ANF\n" "--lambda=function display the intermediate code\n" From 7bd1287b00c409444660783e1f95d2b81d9f3cd2 Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sun, 7 Apr 2024 17:54:52 +0100 Subject: [PATCH 6/7] forgotten new file + optional trailing semicolon --- fn/arithmetic.fn | 16 ++++++++++++++++ src/cmp.h | 28 ++++++++++++++++++++++++++++ src/parser.y | 8 +++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 fn/arithmetic.fn create mode 100644 src/cmp.h diff --git a/fn/arithmetic.fn b/fn/arithmetic.fn new file mode 100644 index 0000000..876b5ad --- /dev/null +++ b/fn/arithmetic.fn @@ -0,0 +1,16 @@ +print(2 + 2); +print(6 - 2); +print(8 / 2); +print(2 * 2); +print(16 % 12); +print(2 ** 2); +print(1 + 4294967295); +print(4294967295 + 4294967295); +print(1234567890123456789 * 2); +print(1234567890123456789 ** 200); +print(4294967295555 % 4294967295555); +print(4294967295555 - 429496729555); +print(-429496729555); +print(-429496729555 / 2); +print(4294967295555 % 429); +print(10 - 1); diff --git a/src/cmp.h b/src/cmp.h new file mode 100644 index 0000000..c2bddb3 --- /dev/null +++ b/src/cmp.h @@ -0,0 +1,28 @@ +#ifndef cekf_cmp_h +# define cekf_cmp_h +/* + * CEKF - VM supporting amb + * Copyright (C) 2022-2023 Bill Hails + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +typedef enum Cmp { + CMP_LT = -1, + CMP_EQ = 0, + CMP_GT = 1 +} Cmp; + +#endif diff --git a/src/parser.y b/src/parser.y index 2168b11..545b365 100644 --- a/src/parser.y +++ b/src/parser.y @@ -169,6 +169,7 @@ static AstCompositeFunction *makeAstCompositeFunction(AstAltFunction *functions, #include "module.h" #include "ast.h" } + %union { char *s; char c; @@ -519,10 +520,14 @@ conslist : %empty { $$ = newAstFunCall(newAstExpression(AST_ | expression ',' conslist { $$ = binOpToFunCall(consSymbol(), $1, newAstExpression(AST_EXPRESSION_TYPE_FUNCALL, AST_EXPRESSION_VAL_FUNCALL($3))); } ; -expression_statements : expression { $$ = newAstExpressions($1, NULL); } +expression_statements : expression optional_semicolon { $$ = newAstExpressions($1, NULL); } | expression ';' expression_statements { $$ = newAstExpressions($1, $3); } ; +optional_semicolon : %empty + | ';' + ; + env : ENV env_expr { $$ = $2; } ; @@ -534,6 +539,7 @@ extends : %empty { $$ = NULL; } ; env_body : '{' definitions '}' { $$ = $2; } + ; symbol : VAR { $$ = newSymbol($1); } ; From 0f62148dc72a91bba619c351c18a40e4725de08d Mon Sep 17 00:00:00 2001 From: Bill Hails Date: Sun, 7 Apr 2024 18:38:58 +0100 Subject: [PATCH 7/7] slightly more optimal checks for divide by zero --- fn/rational.fn | 9 ++++++--- src/arithmetic.c | 36 ++++++++++++++++++++++++++---------- src/step.c | 4 ++-- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/fn/rational.fn b/fn/rational.fn index c8bc38f..bd7131c 100644 --- a/fn/rational.fn +++ b/fn/rational.fn @@ -2,7 +2,7 @@ print(#( "1 * 2", 1 * 2 )); print(#( "1 + 2", 1 + 2 )); print(#( "2 / 3 + 4", 2 / 3 + 4 )); print(#( "4 + 2 / 3 + 4", 4 + 2 / 3 + 4 )); -print(#( "4 + 4 / -6 + 4", 4 + 2 / -3 + 4 )); +print(#( "4 + 4 / -6 + 4", 4 + 4 / - 6 + 4 )); print(#( "2 / 3 + 4 / 5", 2 / 3 + 4 / 5 )); print(#( "(2 / 3) * (4 / 5)", (2 / 3) * (4 / 5) )); print(#( "(6 / 5)", (6 / 5) )); @@ -10,8 +10,11 @@ print(#( "(2 / 3) / (6 / 5)", (2 / 3) / (6 / 5) )); print(#( "(2 / 3) % (4 / 5)", (2 / 3) % (4 / 5) )); print(#( "1/3 % 8", 1/3 % 8 )); print(#( "-9 % 8", -9 % 8 )); -print(#( "(1/2) ** 2", (1/2) ** 2 )); +print(#( "(2/3) ** 2", (2/3) ** 2 )); +print(#( "2 / 3 ** 2", 2 / 3 ** 2 )); print(#( "1 / 2 < 1 / 3", 1/2 < 1/3 )); print(#( "1 / 2 > 1 / 3", 1/2 > 1/3 )); print(#( "1 / 2 < 1", 1/2 < 1 )); -print(#( "1 / 2 > 1", 1/2 > 1 )) +print(#( "1 / 2 > 1", 1/2 > 1 )); +print(#( "1 / 2 <=> 1 / 3", 1/2 <=> 1/3 )); +print(#( "1 / 2 <=> 1", 1/2 <=> 1 )); diff --git a/src/arithmetic.c b/src/arithmetic.c index 43e0813..9785313 100644 --- a/src/arithmetic.c +++ b/src/arithmetic.c @@ -87,22 +87,38 @@ static Value bigIntValue(BigInt *i) { return val; } +static inline Cmp int_cmp_bb(Value left, Value right) { + return cmpBigInt(left.val.bigint, right.val.bigint); +} + +static inline Cmp int_cmp_bi(Value left, Value right) { + return cmpBigIntInt(left.val.bigint, right.val.stdint); +} + +static inline Cmp int_cmp_ib(Value left, Value right) { + return cmpIntBigInt(left.val.stdint, right.val.bigint); +} + +static inline Cmp int_cmp_ii(Value left, Value right) { + return left.val.stdint < right.val.stdint ? CMP_LT : + left.val.stdint == right.val.stdint ? CMP_EQ : + CMP_GT; +} + static Cmp int_cmp(Value left, Value right) { ENTER(int_cmp); Cmp res; if (IS_BIGINT(left)) { if (IS_BIGINT(right)) { - res = cmpBigInt(left.val.bigint, right.val.bigint); + res = int_cmp_bb(left, right); } else { - res = cmpBigIntInt(left.val.bigint, right.val.stdint); + res = int_cmp_bi(left, right); } } else { if (IS_BIGINT(right)) { - res = cmpIntBigInt(left.val.stdint, right.val.bigint); + res = int_cmp_ib(left, right); } else { - res = left.val.stdint < right.val.stdint ? CMP_LT : - left.val.stdint == right.val.stdint ? CMP_EQ : - CMP_GT; + res = int_cmp_ii(left, right); } } LEAVE(int_cmp); @@ -233,7 +249,7 @@ static Value int_div(Value left, Value right) { int save = PROTECT(NULL); if (IS_BIGINT(left)) { if (IS_BIGINT(right)) { - if (int_cmp(right, Zero) == CMP_EQ) { + if (int_cmp_bb(right, Zero) == CMP_EQ) { cant_happen("attempted div zero"); } BigInt *bi = divBigInt(left.val.bigint, right.val.bigint); @@ -249,7 +265,7 @@ static Value int_div(Value left, Value right) { } } else { if (IS_BIGINT(right)) { - if (int_cmp(right, Zero) == CMP_EQ) { + if (int_cmp_bb(right, Zero) == CMP_EQ) { cant_happen("attempted div zero"); } BigInt *bi = divIntBigInt(left.val.stdint, right.val.bigint); @@ -311,7 +327,7 @@ static Value int_mod(Value left, Value right) { int save = PROTECT(NULL); if (IS_BIGINT(left)) { if (IS_BIGINT(right)) { - if (int_cmp(right, Zero) == CMP_EQ) { + if (int_cmp_bb(right, Zero) == CMP_EQ) { cant_happen("attempted mod zero"); } BigInt *bi = modBigInt(left.val.bigint, right.val.bigint); @@ -327,7 +343,7 @@ static Value int_mod(Value left, Value right) { } } else { if (IS_BIGINT(right)) { - if (int_cmp(right, Zero) == CMP_EQ) { + if (int_cmp_bb(right, Zero) == CMP_EQ) { cant_happen("attempted mod zero"); } BigInt *bi = modIntBigInt(left.val.stdint, right.val.bigint); diff --git a/src/step.c b/src/step.c index e73aa9f..793dcf3 100644 --- a/src/step.c +++ b/src/step.c @@ -392,10 +392,10 @@ static void applyProc(int naargs) { #define printCEKF(state) -static int count = 0; +static unsigned long int count = 0; void reportSteps(void) { - printf("%d instructions executed\n", count); + printf("%lu instructions executed\n", count); printf("%d final stack capacity\n", state.S.capacity); }