summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/precedent.15
-rw-r--r--src/eval.c44
-rw-r--r--src/parse.c21
3 files changed, 60 insertions, 10 deletions
diff --git a/doc/precedent.1 b/doc/precedent.1
index 6b98479..0231d84 100644
--- a/doc/precedent.1
+++ b/doc/precedent.1
@@ -68,7 +68,10 @@ literals or key references. The following are examples of key references with ar
\-\- If its first argument is 0, returns 1. Otherwise, returns 0.
\fBsum()\fP
-\-\- Evaluates all its arguments. Returns the sum.
+\-\- Evaluates all its arguments and returns the sum. If any argument is a float, returns a float. Otherwise, returns an int.
+
+\fBsub()\fP
+\-\- Evaluates all its arguments. Subtracts every argument after the first from the first. Returns the result, which is a float if any arguments were floats, or an int if all arguments were ints.
\fBprint()\fP
\-\- Evaluates its first argument and prints it to the terminal.
diff --git a/src/eval.c b/src/eval.c
index 0b28ef4..8adcf8c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -198,23 +198,56 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
}
else if (hash == get_hash("sum")) {
int sum = 0;
+ float fSum = 0;
+ char isFloat = 0;
for (int i = 0; i < symbol->argCount; i++) {
sym_t* v = eval(symbol->args[i], symbolScope);
- sum += symtoi(v);
+ if (v->litType == INT) {
+ sum += symtoi(v);
+ }
+ else if (v->litType == FLOAT) {
+ fSum += symtof(v);
+ isFloat = 1;
+ }
destroy_sym(v);
}
- return init_sym_int(sum);
+ if (!isFloat) {
+ return init_sym_int(sum);
+ }
+ else {
+ return init_sym_float(sum + fSum);
+ }
}
else if (hash == get_hash("sub")) {
sym_t* v1 = eval(symbol->args[0], symbolScope);
- int sum = symtoi(v1);
+ int sum = 0;
+ float fSum = 0;
+ char isFloat = 0;
+ if (v1->litType == INT) {
+ sum = symtoi(v1);
+ }
+ else if (v1->litType == FLOAT) {
+ fSum = symtof(v1);
+ isFloat = 1;
+ }
destroy_sym(v1);
for (int i = 1; i < symbol->argCount; i++) {
sym_t* v = eval(symbol->args[i], symbolScope);
- sum -= symtoi(v);
+ if (v->litType == INT) {
+ sum -= symtoi(v);
+ }
+ else if (v->litType == FLOAT) {
+ fSum -= symtof(v);
+ isFloat = 1;
+ }
destroy_sym(v);
}
- return init_sym_int(sum);
+ if (!isFloat) {
+ return init_sym_int(sum);
+ }
+ else {
+ return init_sym_float(sum + fSum);
+ }
}
else if (hash == get_hash("print")) {
sym_t* v = eval(symbol->args[0], symbolScope);
@@ -222,6 +255,7 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
printf("%d\n", symtoi(v));
}
else if (v->litType == FLOAT) {
+ printf("%.5f\n", symtof(v));
}
else if (v->litType == STRING) {
char* s = symtos(v);
diff --git a/src/parse.c b/src/parse.c
index 18425ac..d1b0f2e 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -24,7 +24,7 @@ sym_t* init_sym_int(int value) {
return init_sym(LITERAL, INT, vp);
}
sym_t* init_sym_float(float value) {
- int* vp = malloc(sizeof(float));
+ float* vp = malloc(sizeof(float));
*vp = value;
return init_sym(LITERAL, FLOAT, vp);
}
@@ -93,20 +93,23 @@ symset_t* parse_symbols(char** str) {
return symbolSet;
}
char* symbolName = calloc(30, sizeof(char));
+ char isFloat = 0;
int i = 0;
while (1) {
symbolName[i] = **str;
- if (**str == ',' || **str == ';') {
+ if (**str == '.') {
+ isFloat = 1;
+ }
+ else if (**str == ',' || **str == ';') {
(*str)++;
symbolName[i] = '\0';
sym_t* symbol;
- /* TODO: float */
/* string */
if (isalpha(symbolName[0])) {
symbol = init_sym_str(symbolName);
}
/* int */
- else {
+ else if (!isFloat) {
int v;
if (symbolName[0] == '-') {
v = atoi(symbolName + 1) * -1;
@@ -116,6 +119,16 @@ symset_t* parse_symbols(char** str) {
}
symbol = init_sym_int(v);
}
+ else {
+ float v;
+ if (symbolName[0] == '-') {
+ v = atof(symbolName + 1) * -1;
+ }
+ else {
+ v = atof(symbolName);
+ }
+ symbol = init_sym_float(v);
+ }
symset_add_symbol(symbolSet, symbol);
break;
}