aboutsummaryrefslogtreecommitdiff
path: root/src/primitives/core.d
diff options
context:
space:
mode:
authorAdrian Kummerlaender2017-04-13 21:51:54 +0200
committerAdrian Kummerlaender2017-04-13 21:51:54 +0200
commitd2126fe52fd3c002631e66fa7d6e2d5cd8862bea (patch)
treecd0bc233912b7ed06c6c4735e7a6475e4099e585 /src/primitives/core.d
parent11d6996d9b56b537946b2894a66f56f5cf3576b8 (diff)
downloadslang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar.gz
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar.bz2
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar.lz
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar.xz
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.tar.zst
slang-d2126fe52fd3c002631e66fa7d6e2d5cd8862bea.zip
Implement deferred word, conditional resolution
Due to the non-trivial way tokens were previously processed the compiler could not safely perform tail-call elimination. Thus the _slang_ evaluation depth was restricted by the maximum call stack size. This issue is mitigated by introducing deferred word resolution - i.e. pushing expanded tokens onto a buffer stack and processing them in an explicit loop. This change ties into the implementation of the language's conditional primitive. The previous implementation did implicitly not support direct nesting of conditional expressions such as: truthA if mainBranch truthB if secondaryMainBranch then else then alternativeBranch else This issue is now made explicit by disallowing direct nesting of conditionals as depicted above. Appropriate exceptions are generated when required and the conditional primitive is reimplemented in a more robust fashion under the assumption that this rule holds. Note that nesting is still fully supported iff. the nested conditional is contained in a deferredly evaluated word. As a positive side effect this will make it slightly harder to generate unreadable code by forcing developers to write simpler words. The main change of the conditional primitive lies in deferring branch token processing until the conditional expression is concluded by `else`. This is achieved by capturing non-dropped tokens in an internal buffer akin to how the word definition operator `ยง` is implemented. The branch buffer is discharged after `else` is evaluated. Discharging is triggered via the newly introduced `result` method of the primitive evaluation module. This avenue for injecting tokens into the processing stream may be used by further primitives in the future.
Diffstat (limited to 'src/primitives/core.d')
-rw-r--r--src/primitives/core.d101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/primitives/core.d b/src/primitives/core.d
new file mode 100644
index 0000000..5b3d43d
--- /dev/null
+++ b/src/primitives/core.d
@@ -0,0 +1,101 @@
+module src.primitives.core;
+
+import std.stdio;
+
+import src.stack;
+import src.definition;
+
+Token[string] variables;
+
+void definition_start() {
+ src.definition.start;
+}
+
+void binary_op_variable_bind() {
+ string name = stack.pop.get!string;
+ Token value = stack.pop;
+ variables[name] = value;
+}
+
+void unary_op_variable_resolve() {
+ string name = stack.pop.get!string;
+
+ if ( name in variables ) {
+ stack.push(variables[name]);
+ }
+}
+
+void binary_op_add() {
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ stack.push(a + b);
+}
+
+void binary_op_multiply() {
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ stack.push(a * b);
+}
+
+void binary_op_divide() {
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ if ( b == 0 ) {
+ throw new Exception("division by 0 undefined");
+ } else {
+ stack.push(a / b);
+ }
+}
+
+void binary_op_modulo() {
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ if ( b == 0 ) {
+ throw new Exception("modulo 0 undefined");
+ } else {
+ stack.push(a % b);
+ }
+}
+
+void unary_op_io_print() {
+ writeln(stack.top);
+}
+
+void unary_op_stack_pop() {
+ stack.pop;
+}
+
+void unary_op_stack_dup() {
+ stack.push(stack.top);
+}
+
+void binary_op_stack_swp() {
+ auto b = stack.pop;
+ auto a = stack.pop;
+
+ stack.push(b);
+ stack.push(a);
+
+}
+
+void binary_cond_lt() {
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ stack.push(a < b);
+}
+
+void binary_cond_eq() {
+ auto b = stack.pop;
+ auto a = stack.pop;
+
+ stack.push(a == b);
+}
+
+void integral_value_bool(bool value) {
+ stack.push(Token(value));
+}