aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--repl.d178
-rw-r--r--src/definition.d57
-rw-r--r--src/primitives.d69
-rw-r--r--src/stack.d38
4 files changed, 186 insertions, 156 deletions
diff --git a/repl.d b/repl.d
index b70f8ac..89c3104 100644
--- a/repl.d
+++ b/repl.d
@@ -1,123 +1,34 @@
import std.stdio;
import std.string;
import std.conv;
+import std.variant;
import std.typecons;
import std.container : SList;
-import std.container : DList;
-
-import std.variant;
-
-alias Token = Algebraic!(int, string);
-SList!Token stack;
-DList!Token[string] words;
-int[string] variables;
-Nullable!(DList!Token) definition;
+import src.stack;
-void startDefinition()
-in { assert( definition.isNull); }
-out { assert(!definition.isNull); }
-body {
- definition = DList!Token();
-}
-
-void endDefinition()
-in { assert(!definition.isNull); }
-out { assert( definition.isNull); }
-body {
- string wordToBeDefined;
-
- definition.front.visit!(
- (int x ) => wordToBeDefined = "",
- (string name) => wordToBeDefined = name
- );
+static import src.definition;
+static import src.primitives;
- if ( wordToBeDefined == "" ) {
- throw new Exception("words may not be numeric");
- }
-
- definition.removeFront;
- words[wordToBeDefined] = definition;
- definition.nullify;
-}
-
-void append(ref Nullable!(DList!Token) definition, int value) {
- definition.insertBack(Token(value));
-}
-
-void append(ref Nullable!(DList!Token) definition, string word) {
- if ( word == ";" ) {
- endDefinition();
- } else {
- definition.insertBack(Token(word));
- }
+void process(int x) {
+ stack.push(x);
}
-void evaluate(string word) {
- switch ( word ) {
- case "§":
- startDefinition();
- break;
- case "$":
- string name = stack.pop().get!string;
- int value = stack.pop().get!int;
-
- variables[name] = value;
- break;
- case "@":
- string name = stack.pop().get!string;
-
- if ( name in variables ) {
- stack.push(variables[name]);
- }
- break;
- case "+":
- int b = stack.pop().get!int;
- int a = stack.pop().get!int;
-
- stack.push(a + b);
- break;
- case "*":
- int b = stack.pop().get!int;
- int a = stack.pop().get!int;
-
- stack.push(a * b);
- break;
- case "/":
- 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);
- }
- break;
- case "%":
- 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);
- }
- break;
- case ".":
- stack.pop;
- break;
- case "'":
- writeln(stack.top);
- break;
- default:
- if ( word in words ) {
- foreach ( token; words[word] ) {
+void process(string word) {
+ try {
+ if ( !src.primitives.evaluate(word) ) {
+ if ( word in src.definition.words ) {
+ foreach ( token; src.definition.words[word] ) {
process(token);
}
} else {
stack.push(word);
}
+ }
+ }
+ catch (Exception ex) {
+ writeln("Error: ", ex.msg);
}
}
@@ -128,63 +39,18 @@ void process(Token token) {
);
}
-void process(int x) {
- stack.push(x);
-}
-
-void process(string word) {
- try {
- evaluate(word);
- }
- catch (Exception ex) {
- writeln("Error: ", ex.msg);
- }
-}
-
-void push(ref SList!Token stack, int value) {
- if ( definition.isNull ) {
- stack.insertFront(Token(value));
- } else {
- definition.append(value);
- }
-}
-
-void push(ref SList!Token stack, string word) {
- if ( definition.isNull ) {
- stack.insertFront(Token(word));
- } else {
- definition.append(word);
- }
-}
-
-Token top(ref SList!Token stack) {
- if ( stack.empty ) {
- throw new Exception("stack is empty");
- } else {
- return stack.front;
- }
-}
-
-Token pop(ref SList!Token stack) {
- Token token = stack.top;
- stack.removeFront;
- return token;
-}
-
void main() {
while ( !stdin.eof ) {
foreach ( token; stdin.readln.split ) {
- if ( definition.isNull ) {
- if ( token.isNumeric ) {
- process(parse!int(token));
- } else {
- process(token);
+ if ( token.isNumeric ) {
+ immutable int value = parse!int(token);
+
+ if ( !src.definition.handle(value) ) {
+ process(value);
}
} else {
- if ( token.isNumeric ) {
- definition.append(parse!int(token));
- } else {
- definition.append(token);
+ if ( !src.definition.handle(token) ) {
+ process(token);
}
}
}
diff --git a/src/definition.d b/src/definition.d
new file mode 100644
index 0000000..dd4dddc
--- /dev/null
+++ b/src/definition.d
@@ -0,0 +1,57 @@
+module src.definition;
+
+import std.string;
+import std.variant;
+import std.typecons;
+import std.container : DList;
+
+import src.stack : Token;
+
+alias Words = DList!Token[string];
+
+Nullable!(DList!Token) definition;
+Words words;
+
+void start() {
+ definition = DList!Token();
+}
+
+void end() {
+ string wordToBeDefined;
+
+ definition.front.visit!(
+ (int x ) => wordToBeDefined = "",
+ (string name) => wordToBeDefined = name
+ );
+
+ if ( wordToBeDefined == "" ) {
+ throw new Exception("words may not be numeric");
+ }
+
+ definition.removeFront;
+ words[wordToBeDefined] = definition;
+ definition.nullify;
+}
+
+bool handle(int value) {
+ if ( definition.isNull ) {
+ return false;
+ } else {
+ definition.insertBack(Token(value));
+ return true;
+ }
+}
+
+bool handle(string word) {
+ if ( definition.isNull ) {
+ return false;
+ } else {
+ if ( word == ";" ) {
+ end();
+ } else {
+ definition.insertBack(Token(word));
+ }
+
+ return true;
+ }
+}
diff --git a/src/primitives.d b/src/primitives.d
new file mode 100644
index 0000000..0be6836
--- /dev/null
+++ b/src/primitives.d
@@ -0,0 +1,69 @@
+module src.primitives;
+
+import std.stdio;
+
+import src.stack;
+import src.definition;
+
+int[string] variables;
+
+bool evaluate(string word) {
+ switch ( word ) {
+ case "§":
+ src.definition.start;
+ return true;
+ case "$":
+ string name = stack.pop.get!string;
+ int value = stack.pop.get!int;
+
+ variables[name] = value;
+ return true;
+ case "@":
+ string name = stack.pop.get!string;
+
+ if ( name in variables ) {
+ stack.push(variables[name]);
+ }
+ return true;
+ case "+":
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ stack.push(a + b);
+ return true;
+ case "*":
+ int b = stack.pop.get!int;
+ int a = stack.pop.get!int;
+
+ stack.push(a * b);
+ return true;
+ case "/":
+ 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);
+ }
+ return true;
+ case "%":
+ 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);
+ }
+ return true;
+ case ".":
+ stack.pop;
+ return true;
+ case "'":
+ writeln(stack.top);
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/stack.d b/src/stack.d
new file mode 100644
index 0000000..756dafc
--- /dev/null
+++ b/src/stack.d
@@ -0,0 +1,38 @@
+module src.stack;
+
+import std.variant;
+import std.string;
+import std.container : SList;
+
+static import src.definition;
+
+alias Token = Algebraic!(int, string);
+alias Stack = SList;
+
+Stack!Token stack;
+
+Token top(ref Stack!Token stack) {
+ if ( stack.empty ) {
+ throw new Exception("stack is empty");
+ } else {
+ return stack.front;
+ }
+}
+
+Token pop(ref Stack!Token stack) {
+ Token token = stack.top;
+ stack.removeFront;
+ return token;
+}
+
+void push(ref Stack!Token stack, int value) {
+ if ( !src.definition.handle(value) ) {
+ stack.insertFront(Token(value));
+ }
+}
+
+void push(ref Stack!Token stack, string word) {
+ if ( !src.definition.handle(word) ) {
+ stack.insertFront(Token(word));
+ }
+}