From c0bf1dc624f373872d5dd8e67d756d3ec70830e7 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Wed, 12 Apr 2017 11:45:40 +0200 Subject: Implement support for variables, mixed types in data stack --- repl.d | 117 +++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 32 deletions(-) diff --git a/repl.d b/repl.d index 9117c28..9f1d131 100644 --- a/repl.d +++ b/repl.d @@ -6,37 +6,51 @@ import std.typecons; import std.container : SList; import std.container : DList; -SList!int stack; -DList!string[string] words; -Nullable!(DList!string) definition; +import std.variant; + +alias Token = Algebraic!(int, string); + +SList!Token stack; +DList!Token[string] words; +int[string] variables; +Nullable!(DList!Token) definition; void startDefinition() in { assert( definition.isNull); } out { assert(!definition.isNull); } body { - definition = DList!string(); + definition = DList!Token(); } void endDefinition() in { assert(!definition.isNull); } out { assert( definition.isNull); } body { - auto wordToBeDefined = definition.front; + string wordToBeDefined; + + definition.front.visit!( + (int x ) => wordToBeDefined = "", + (string name) => wordToBeDefined = name + ); - if ( wordToBeDefined.isNumeric ) { + if ( wordToBeDefined == "" ) { throw new Exception("words may not be numeric"); - } else { - definition.removeFront; - words[wordToBeDefined] = definition; - definition.nullify; } + + definition.removeFront; + words[wordToBeDefined] = definition; + definition.nullify; } -void append(ref Nullable!(DList!string) definition, string token) { - if ( token == ";" ) { +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); + definition.insertBack(Token(word)); } } @@ -45,15 +59,28 @@ void evaluate(string 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 "+": - auto a = stack.pop(); - auto b = stack.pop(); + int a = stack.pop().get!int; + int b = stack.pop().get!int; stack.push(a + b); break; case "*": - auto a = stack.pop(); - auto b = stack.pop(); + int a = stack.pop().get!int; + int b = stack.pop().get!int; stack.push(a * b); break; @@ -61,42 +88,68 @@ void evaluate(string word) { writeln(stack.front); break; default: - foreach ( token; words[word] ) { - process(token); + if ( word in words ) { + foreach ( token; words[word] ) { + process(token); + } + } else { + stack.push(word); } } } -void process(string token) { - if ( token.isNumeric ) { - stack.push(parse!int(token)); +void process(Token token) { + token.visit!( + (int x ) => process(x), + (string word) => process(word) + ); +} + +void process(int x) { + stack.push(x); +} + +void process(string word) { + evaluate(word); +} + +void push(ref SList!Token stack, int value) { + if ( definition.isNull ) { + stack.insertFront(Token(value)); } else { - evaluate(token); + definition.append(value); } } -void push(ref SList!int stack, int value) { +void push(ref SList!Token stack, string word) { if ( definition.isNull ) { - stack.insertFront(value); + stack.insertFront(Token(word)); } else { - definition.append(to!string(value)); + definition.append(word); } } -int pop(ref SList!int stack) { - auto x = stack.front; +Token pop(ref SList!Token stack) { + Token token = stack.front; stack.removeFront; - - return x; + return token; } void main() { while ( !stdin.eof ) { foreach ( token; stdin.readln.split ) { if ( definition.isNull ) { - process(token); + if ( token.isNumeric ) { + process(parse!int(token)); + } else { + process(token); + } } else { - definition.append(token); + if ( token.isNumeric ) { + definition.append(parse!int(token)); + } else { + definition.append(token); + } } } } -- cgit v1.2.3