summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2023-03-04 01:19:17 -0800
committerKai Stevenson <kai@kaistevenson.com>2023-03-04 01:21:14 -0800
commit2127b746f0eecb657b31653ad5967623f994cbaf (patch)
tree9df6e054410102ed620aae7b497f0dce66b6efc3
parentf52050d53e698975d6598da86ddd99100ae70fdf (diff)
added any(), all(), one(). replaced not() with none()
-rw-r--r--doc/precedent.127
-rw-r--r--examples/boolean.pcdt2
-rw-r--r--examples/boundedrecursion.pcdt2
-rw-r--r--examples/while.pcdt5
-rw-r--r--src/eval.c57
-rw-r--r--stdlib/math.pcdt2
6 files changed, 80 insertions, 15 deletions
diff --git a/doc/precedent.1 b/doc/precedent.1
index 1365ee8..a9c64e2 100644
--- a/doc/precedent.1
+++ b/doc/precedent.1
@@ -40,7 +40,10 @@ are examples of literal values: [ 123, "hello world", 9.81 ]. A key without argu
is simply stated as a word. The following are examples of key references:
[ myVar, arg0 ]. A key reference may have any number of arguments, which may be
literals or key references. The following are examples of key references with arguments:
-[ print("hello world"), print(myVar), print(eq(1, 2)) ].
+[ print("hello world"), print(myVar), print(eq(1, 2)) ]. Literals and keys may be separated by commas, semicolons, or spaces, to taste.
+
+.SH DETAILS
+Logical functions treat all non-zero integer values as TRUE, and 0 as FALSE. Passing a float or a string to such a function will usually result in an error. Some logical functions short-circuit, meaning that they will cease evaluation as soon as their condition can no longer be met. For example, if the first argument to all() is FALSE, it will not evaluate the rest of its arguments.
.SH FUNCTIONS
\fBroot() OR ()\fP
@@ -50,7 +53,7 @@ literals or key references. The following are examples of key references with ar
\-\- Returns a pointer to its first argument, not evaluating it.
\fBeval()\fP
-\-\- Evaluates its first argument, passing the the rest of its arguments as arg0, arg1... etc. Essentially undoes ref().
+\-\- Evaluates its first argument, passing the the rest of its arguments as argFALSE, argTRUE... etc. Essentially undoes ref().
\fBstore()\fP
\-\- Stores the evaluation of its first argument under the name specified by the (string) evaluation of its second argument. Use with ref() to store functions, or without to store variables.
@@ -59,13 +62,25 @@ literals or key references. The following are examples of key references with ar
\-\- Stores the evaluation of its first argument under the name specified by the (string) evaluation of its second argument, in the same manner as store(). Update() differs from store when the key is not found in the local scope. In this case, update() searches upwards for the first scope containing the key, and overwrites its value.
\fBeq()\fP
-\-\- Evaluates all of its arguments. If they are all equivalent, returns 1. Otherwise, returns 0. Can accept ints, floats, or strings. Strings cannot be mixed with floats or ints.
+\-\- Evaluates all of its arguments. If they are all equivalent, returns TRUE. Otherwise, returns FALSE. Can accept ints, floats, or strings. Strings cannot be mixed with floats or ints.
+
+\fBany()\fP
+\-\- Evaluates all of its arguments. If any are not FALSE, returns TRUE. Otherwise, returns FALSE. Equivalent to the logical operator OR. Short-circuits.
+
+\fBall()\fP
+\-\- Evaluates all of its arguments. If all are not FALSE, returns TRUE. Otherwise, returns FALSE. Equivalent to the logical operator AND. Short-circuits.
+
+\fBone()\fP
+\-\- Evaluates all of its arguments. If exactly one argument is not FALSE, returns TRUE. Otherwise, returns FALSE. Equivalent to the logical operator XOR. Short-circuits.
+
+\fBnone()\fP
+\-\- Evaluates all of its arguments. If none are TRUE, returns TRUE. Otherwise, returns FALSE. Short-circuits.
\fBif()\fP
-\-\- If its first argument is not 0, evaluates the rest of its arguments. Does not return a value.
+\-\- If its first argument is TRUE, evaluates the rest of its arguments.
-\fBnot()\fP
-\-\- If its first argument is 0, returns 1. Otherwise, returns 0.
+\fBwhile()\fP
+\-\- If its first argument is TRUE, evaluates the rest of its arguments. Then, if its first argument is still TRUE, evaluates the rest of its arguments again. Repeats until its first argument is FALSE.
\fBsum()\fP
\-\- Evaluates all its arguments and returns the sum. If any argument is a float, returns a float. Otherwise, returns an int.
diff --git a/examples/boolean.pcdt b/examples/boolean.pcdt
index de6f04f..553a602 100644
--- a/examples/boolean.pcdt
+++ b/examples/boolean.pcdt
@@ -9,7 +9,7 @@ if(res
print("equals")
)
-if(not(res)
+if(none(res)
print("does not equal")
)
diff --git a/examples/boundedrecursion.pcdt b/examples/boundedrecursion.pcdt
index 12981da..bbe4194 100644
--- a/examples/boundedrecursion.pcdt
+++ b/examples/boundedrecursion.pcdt
@@ -2,7 +2,7 @@ store(1000, "maxSize");
store(
ref((
print(arg0);
- if(not(eq(arg0, maxSize))
+ if(none(eq(arg0, maxSize))
incFunc(sum(1, arg0));
)
));
diff --git a/examples/while.pcdt b/examples/while.pcdt
new file mode 100644
index 0000000..7a267fc
--- /dev/null
+++ b/examples/while.pcdt
@@ -0,0 +1,5 @@
+store(0, "i")
+while(none(eq(i, 10)), (
+ print(i);
+ update(sum(i, 1), "i")
+))
diff --git a/src/eval.c b/src/eval.c
index b583fc6..8b41f38 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -189,6 +189,57 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
}
return init_sym_int(1);
}
+ /* OR */
+ else if (hash == get_hash("any")) {
+ for (int i = 0; i < symbol->argCount; i++) {
+ sym_t* v = eval(symbol->args[i], symbolScope);
+ if (symtoi(v) != 0) {
+ destroy_sym(v);
+ return init_sym_int(1);
+ }
+ destroy_sym(v);
+ }
+ return init_sym_int(0);
+ }
+ /* AND */
+ else if (hash == get_hash("all")) {
+ for (int i = 0; i < symbol->argCount; i++) {
+ sym_t* v = eval(symbol->args[i], symbolScope);
+ if (symtoi(v) == 0) {
+ destroy_sym(v);
+ return init_sym_int(0);
+ }
+ destroy_sym(v);
+ }
+ return init_sym_int(1);
+ }
+ /* XOR */
+ else if (hash == get_hash("one")) {
+ char b = 0;
+ for (int i = 0; i < symbol->argCount; i++) {
+ sym_t* v = eval(symbol->args[i], symbolScope);
+ if (symtoi(v) == 1) {
+ if (b == 1) {
+ destroy_sym(v);
+ return init_sym_int(0);
+ }
+ b = 1;
+ }
+ destroy_sym(v);
+ }
+ return init_sym_int(b);
+ }
+ else if (hash == get_hash("none")) {
+ for (int i = 0; i < symbol->argCount; i++) {
+ sym_t* v = eval(symbol->args[i], symbolScope);
+ if (symtoi(v) == 1) {
+ destroy_sym(v);
+ return init_sym_int(0);
+ }
+ destroy_sym(v);
+ }
+ return init_sym_int(1);
+ }
else if (hash == get_hash("if")) {
sym_t* v = eval(symbol->args[0], symbolScope);
int si = symtoi(v);
@@ -212,12 +263,6 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
}
}
}
- else if (hash == get_hash("not")) {
- sym_t* v = eval(symbol->args[0], symbolScope);
- int b = symtoi(v);
- destroy_sym(v);
- return init_sym_int(!b);
- }
else if (hash == get_hash("sum")) {
int sum = 0;
float fSum = 0;
diff --git a/stdlib/math.pcdt b/stdlib/math.pcdt
index 3f375ae..99dd937 100644
--- a/stdlib/math.pcdt
+++ b/stdlib/math.pcdt
@@ -1,7 +1,7 @@
store(
ref((
store(0, "last")
- if(not(eq(arg0, 1))
+ if(none(eq(arg0, 1))
update(multiply(sub(arg0, 1), arg1), "last")
)
sum(arg1, last)