summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h6
-rw-r--r--array.c91
-rw-r--r--functions.c102
-rw-r--r--lexer.c13
-rw-r--r--print.c16
-rw-r--r--quadnames.c27
-rw-r--r--symbol.c8
7 files changed, 220 insertions, 43 deletions
diff --git a/apl9.h b/apl9.h
index f65e8f7..f15cd77 100644
--- a/apl9.h
+++ b/apl9.h
@@ -22,6 +22,7 @@ typedef enum
typedef enum
{
AtypeInt,
+ AtypeFloat,
AtypeArray,
} arrayDataType;
@@ -58,6 +59,7 @@ struct Array
union {
char *rawdata;
vlong *intdata;
+ double *floatdata;
Array **arraydata;
};
};
@@ -154,11 +156,13 @@ Statement *lexline(Rune *);
/* array.c */
Array *mkscalarint(vlong);
+Array *mkscalarfloat(double);
Array *duparray(Array *);
int simplearray(Array *);
int simplescalar(Array *);
Array *extend(Array *, Array *);
int scalarextend(Array *, Array *, Array **, Array **);
+int commontype(Array *, Array *, Array **, Array **, int);
Array *arrayitem(Array *, int);
Array *simplifyarray(Array *);
@@ -169,7 +173,6 @@ Datum *eval(Statement *);
Symbol *getsym(Symtab *, Rune *);
Symtab *newsymtab(void);
void freesymtab(Symtab *);
-vlong globalIO(void);
/* memory.c */
void *emalloc(ulong);
@@ -230,3 +233,4 @@ extern Symtab *globalsymtab; /* symbol.c */
extern Symtab *currentsymtab; /* symbol.c */
extern int alloccounts; /* memory.c */
extern QuadnameDef quadnames[]; /* quadnames.c */
+extern int printprecision; /* print.c */ \ No newline at end of file
diff --git a/array.c b/array.c
index 7675144..4208d9f 100644
--- a/array.c
+++ b/array.c
@@ -4,8 +4,11 @@
#include "apl9.h"
+Array *inttofloatarray(Array *);
+
int datasizes[] = {
[AtypeInt] = sizeof(vlong),
+ [AtypeFloat] = sizeof(double),
[AtypeArray] = sizeof(Array *)
};
@@ -14,7 +17,14 @@ mkscalarint(vlong i)
{
Array *a = allocarray(AtypeInt, 0, 1);
a->intdata[0] = i;
+ return a;
+}
+Array *
+mkscalarfloat(double f)
+{
+ Array *a = allocarray(AtypeFloat, 0, 1);
+ a->floatdata[0] = f;
return a;
}
@@ -39,7 +49,7 @@ simplearray(Array *a)
int
simplescalar(Array *a)
{
- return simplearray(a) && a->rank == 0;
+ return a->rank == 0 && a->type != AtypeArray;
}
Array *
@@ -81,6 +91,40 @@ scalarextend(Array *a, Array *b, Array **aa, Array **bb)
}
Array *
+inttofloatarray(Array *a)
+{
+ Array *b = allocarray(AtypeFloat, a->rank, a->size);
+ for(int i = 0; i < a->rank; i++)
+ b->shape[i] = a->shape[i];
+ for(int i = 0; i < a->size; i++)
+ b->floatdata[i] = a->intdata[i];
+ return b;
+}
+
+int
+commontype(Array *a, Array *b, Array **aa, Array **bb, int forcefloat)
+{
+ /* When A and B are numeric arrays, set aa and bb
+ to arrays that have compatible types, with the same data.
+ */
+ if(forcefloat){
+ *aa = a->type == AtypeFloat ? fnSame(a) : inttofloatarray(a);
+ *bb = b->type == AtypeFloat ? fnSame(b) : inttofloatarray(b);
+ }else if(a->type == b->type){
+ *aa = fnSame(a);
+ *bb = fnSame(b);
+ }else if(a->type == AtypeFloat && b->type == AtypeInt){
+ *aa = fnSame(a);
+ *bb = inttofloatarray(b);
+ }else if(a->type == AtypeInt && b->type == AtypeFloat){
+ *aa = inttofloatarray(a);
+ *bb = fnSame(b);
+ }else
+ return 0;
+ return 1;
+}
+
+Array *
arrayitem(Array *a, int index)
{
Array *res = nil;
@@ -88,6 +132,9 @@ arrayitem(Array *a, int index)
case AtypeInt:
res = mkscalarint(a->intdata[index]);
break;
+ case AtypeFloat:
+ res = mkscalarfloat(a->floatdata[index]);
+ break;
case AtypeArray:
res = a->arraydata[index];
incref(res);
@@ -106,14 +153,38 @@ simplifyarray(Array *a)
if(a->type != AtypeArray || a->size == 0)
return fnSame(a);
int type = a->arraydata[0]->type;
+ int canfloat = type == AtypeFloat || type == AtypeInt;
+ int sametype = 1;
int i;
- for(i = 0; i < a->size; i++)
- if(a->arraydata[i]->type != type || a->arraydata[i]->rank != 0)
- return fnSame(a);
- Array *b = allocarray(type, a->rank, a->size);
- for(i = 0; i < a->rank; i++)
- b->shape[i] = a->shape[i];
- for(i = 0; i < a->size; i++)
- memcpy(b->rawdata + i * datasizes[type], a->arraydata[i]->rawdata, datasizes[type]);
- return b;
+
+ for(i = 0; i < a->size; i++){
+ int t = a->arraydata[i]->type;
+ canfloat = canfloat && (t == AtypeFloat || t == AtypeInt);
+ sametype = sametype && (t == type);
+ if(a->arraydata[i]->rank != 0)
+ return fnSame(a); /* cannot be simplified */
+ }
+
+ if(sametype){
+ Array *b = allocarray(type, a->rank, a->size);
+ b->stranded = a->stranded;
+ for(i = 0; i < a->rank; i++)
+ b->shape[i] = a->shape[i];
+ for(i = 0; i < a->size; i++)
+ memcpy(b->rawdata + i * datasizes[type], a->arraydata[i]->rawdata, datasizes[type]);
+ return b;
+ }else if(canfloat){
+ Array *b = allocarray(AtypeFloat, a->rank, a->size);
+ b->stranded = a->stranded;
+ for(i = 0; i < a->rank; i++)
+ b->shape[i] = a->shape[i];
+ for(i = 0; i < a->size; i++){
+ if(a->arraydata[i]->type == AtypeFloat)
+ b->floatdata[i] = a->arraydata[i]->floatdata[0];
+ else
+ b->floatdata[i] = a->arraydata[i]->intdata[0];
+ }
+ return b;
+ }else
+ return fnSame(a);
} \ No newline at end of file
diff --git a/functions.c b/functions.c
index 5fa9305..411f90b 100644
--- a/functions.c
+++ b/functions.c
@@ -191,7 +191,7 @@ fnIndexGenerator(Array *right)
vlong n = right->intdata[0];
Array *res = allocarray(AtypeInt, 1, n);
res->shape[0] = n;
- vlong io = globalIO();
+ vlong io = currentsymtab->io;
for(vlong i = 0; i < n; i++)
res->intdata[i] = i + io;
return res;
@@ -239,11 +239,23 @@ fnPlus(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] += rightarr->intdata[i];
+ int typeok = commontype(leftarr, rightarr, &left, &right, 0);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++){
+ if(res->type == AtypeFloat)
+ res->floatdata[i] += right->floatdata[i];
+ else if(res->type == AtypeInt)
+ res->intdata[i] += right->intdata[i];
+ }
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
@@ -258,11 +270,23 @@ fnMinus(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] -= rightarr->intdata[i];
+ int typeok = commontype(leftarr, rightarr, &left, &right, 0);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++){
+ if(res->type == AtypeFloat)
+ res->floatdata[i] -= right->floatdata[i];
+ else if(res->type == AtypeInt)
+ res->intdata[i] -= right->intdata[i];
+ }
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
@@ -277,11 +301,23 @@ fnTimes(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] *= rightarr->intdata[i];
+ int typeok = commontype(leftarr, rightarr, &left, &right, 0);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++){
+ if(res->type == AtypeFloat)
+ res->floatdata[i] *= right->floatdata[i];
+ else if(res->type == AtypeInt)
+ res->intdata[i] *= right->intdata[i];
+ }
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
@@ -296,11 +332,19 @@ fnDivide(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] /= rightarr->intdata[i];
+ int typeok = commontype(leftarr, rightarr, &left, &right, 1);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++)
+ res->floatdata[i] /= right->floatdata[i];
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
@@ -315,11 +359,23 @@ fnPower(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] = pow(res->intdata[i], rightarr->intdata[i]);
+ int typeok = commontype(leftarr, rightarr, &left, &right, 0);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++){
+ if(res->type == AtypeFloat)
+ res->floatdata[i] = pow(res->floatdata[i], right->floatdata[i]);
+ else if(res->type == AtypeInt)
+ res->intdata[i] = pow(res->intdata[i], right->intdata[i]);
+ }
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
@@ -334,11 +390,19 @@ fnLogarithm(Array *left, Array *right)
exits(nil);
}
- Array *res = duparray(leftarr);
- for(int i = 0; i < leftarr->size; i++)
- res->intdata[i] = log(rightarr->intdata[i])/log(res->intdata[i]);
+ int typeok = commontype(leftarr, rightarr, &left, &right, 1);
+ if(!typeok){
+ print("Types don't match lol\n");
+ exits(nil);
+ }
+
+ Array *res = duparray(left);
+ for(int i = 0; i < left->size; i++)
+ res->floatdata[i] = log(right->floatdata[i])/log(res->floatdata[i]);
freearray(leftarr);
freearray(rightarr);
+ freearray(left);
+ freearray(right);
return res;
}
diff --git a/lexer.c b/lexer.c
index d72cdd7..5318924 100644
--- a/lexer.c
+++ b/lexer.c
@@ -88,13 +88,18 @@ lexline(Rune *line)
}else if(isdigitrune(line[offset])){
char buf[64];
char *p = buf;
- while(isdigitrune(line[offset])){
- p += runetochar(p, &line[offset]);
- offset++;
+ int floating = 0;
+get_digits:
+ while(isdigitrune(line[offset]))
+ p += runetochar(p, &line[offset++]);
+ if(!floating && line[offset] == '.'){
+ p += runetochar(p, &line[offset++]);
+ floating = 1;
+ goto get_digits;
}
*p = 0;
stmt->toks[stmt->ntoks].tag = ArrayTag;
- stmt->toks[stmt->ntoks].array = mkscalarint(atoll(buf));
+ stmt->toks[stmt->ntoks].array = floating ? mkscalarfloat(atof(buf)) : mkscalarint(atoll(buf));
}else if(runestrchr(L"⍺⍵", line[offset])){
Rune *name = L"?";
name[0] = line[offset];
diff --git a/print.c b/print.c
index bf1be0c..ae29a01 100644
--- a/print.c
+++ b/print.c
@@ -4,6 +4,8 @@
#include "apl9.h"
+int printprecision = 10;
+
void strdims(Rune *, int *, int *);
Rune *printborder(Rune *, int *, int, int);
Rune *strline(Rune *, int);
@@ -69,7 +71,7 @@ pparray(Array *a)
rowcount *= a->shape[i];
}
Rune **rowstrs = mallocz(sizeof(Rune *) * rowcount, 1);
- int boxing = a->type == AtypeArray;
+ int boxing = !simplearray(a);
char *align = a->type == AtypeArray ? "-" : "";
for(int i = 0; i < a->size; i++){
@@ -79,6 +81,18 @@ pparray(Array *a)
free(arrstr);
}else if(a->type == AtypeInt)
elemstrs[i] = runesmprint("%lld", a->intdata[i]);
+ else if(a->type == AtypeFloat){
+ char *fmt = smprint("%%.%df", printprecision);
+ elemstrs[i] = runesmprint(fmt, a->floatdata[i]);
+ free(fmt);
+ Rune *p = &elemstrs[i][runestrlen(elemstrs[i])-1];
+ int done = 0;
+ while((*p == '0' || *p == '.') && !done){
+ if(*p == '.')
+ done = 1;
+ *p-- = 0; /* remove trailing 0's */
+ }
+ }
}
int lastdim = a->rank ? a->shape[a->rank-1] : 1;
diff --git a/quadnames.c b/quadnames.c
index b765e58..14c431e 100644
--- a/quadnames.c
+++ b/quadnames.c
@@ -8,10 +8,13 @@ Datum *getquad(void);
int setquad(Datum);
Datum *getio(void);
int setio(Datum);
+Datum *getpp(void);
+int setpp(Datum);
QuadnameDef quadnames[] = {
{L"⎕", NameTag, getquad, setquad, nil, nil},
{L"⎕IO", NameTag, getio, setio, nil, nil},
+ {L"⎕PP", NameTag, getpp, setpp, nil, nil},
{nil, 0, nil, nil, nil, nil} /* MUST BE LAST */
};
@@ -60,7 +63,7 @@ getio(void)
{
Datum *d = mallocz(sizeof(Datum), 1);
d->tag = ArrayTag;
- d->array = mkscalarint(globalIO());
+ d->array = mkscalarint(currentsymtab->io);
return d;
}
@@ -74,4 +77,26 @@ setio(Datum new)
currentsymtab->io = new.array->intdata[0];
return 1;
}
+}
+
+/* ⎕PP */
+Datum *
+getpp(void)
+{
+ Datum *d = mallocz(sizeof(Datum), 1);
+ d->tag = ArrayTag;
+ d->array = mkscalarint(printprecision);
+ return d;
+}
+
+int
+setpp(Datum new)
+{
+ if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || new.array->intdata[0] < 0){
+ print("⎕PP: domain error\n");
+ return 0;
+ }else{
+ printprecision = new.array->intdata[0];
+ return 1;
+ }
} \ No newline at end of file
diff --git a/symbol.c b/symbol.c
index 938ab99..9b91cd1 100644
--- a/symbol.c
+++ b/symbol.c
@@ -30,7 +30,7 @@ newsymtab(void)
Symtab *tab = emalloc(sizeof(Symtab));
tab->nsyms = 0;
tab->syms = nil;
- tab->io = currentsymtab ? globalIO() : 1;
+ tab->io = currentsymtab ? currentsymtab->io : 1;
return tab;
}
@@ -47,9 +47,3 @@ freesymtab(Symtab *tab)
free(tab->syms);
free(tab);
}
-
-vlong
-globalIO(void)
-{
- return currentsymtab->io;
-} \ No newline at end of file