Index: main.d ================================================================== --- main.d +++ main.d @@ -4,14 +4,14 @@ * * Entry point for Polemy interpreter. */ import std.stdio; -import polemy.lex; -import polemy.parse; - -static ~this() { readln(); } // workaround for enabling "pause" under Poseidon +import polemy.eval; + +version(unittest) + static ~this() { readln(); } // workaround for enabling "pause" under Poseidon void main() { writeln( "test ok" ); } Index: polemy/ast.d ================================================================== --- polemy/ast.d +++ polemy/ast.d @@ -1,6 +1,6 @@ -/* +/** * Authors: k.inaba * License: NYSL 0.9982 http://www.kmonos.net/nysl/ * * Syntax tree for Polemy programming language. */ Index: polemy/eval.d ================================================================== --- polemy/eval.d +++ polemy/eval.d @@ -9,10 +9,11 @@ import polemy.lex : LexPosition; import polemy.ast; import polemy.parse; import polemy.runtime; import std.typecons; +import std.stdio; Context createGlobalContext() { auto ctx = new Context; ctx.add("+", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ @@ -44,10 +45,16 @@ throw new PolemyRuntimeException("/ takes two arguments!! ["~to!string(pos)~"]"); if( auto x = cast(IntValue)args[0] ) if( auto y = cast(IntValue)args[1] ) return new IntValue(x.data/y.data); throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); + })); + ctx.add("print", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ + foreach(a; args) + write(a); + writeln(""); + return new UndefinedValue; })); return ctx; } Tuple!(Value,"val",Context,"ctx") evalString(T...)(T params) @@ -169,5 +176,10 @@ { auto r = evalString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); f();`); assert( r.ctx["x"] == new IntValue(BigInt(4)) ); assert( r.val == new IntValue(BigInt(4)) ); } +unittest +{ + evalString(`print("Hello, world!");`); + evalString(`print(fun(){});`); +} Index: polemy/lex.d ================================================================== --- polemy/lex.d +++ polemy/lex.d @@ -45,12 +45,17 @@ } /// Represents a lexer token class Token -{ - enum Kind {identifier, stringLiteral, number}; +{ + /// currently we have three kinds of token + enum Kind { + identifier, /// anything other than others + stringLiteral, /// "string literal" + number /// 42 + }; immutable LexPosition pos; /// position where the token occurred in the source immutable string str; /// the token string itself immutable Kind kind; /// which kind of token? mixin SimpleConstructor; Index: polemy/parse.d ================================================================== --- polemy/parse.d +++ polemy/parse.d @@ -1,6 +1,6 @@ -/* +/** * Authors: k.inaba * License: NYSL 0.9982 http://www.kmonos.net/nysl/ * * Parser for Polemy programming language */ Index: polemy/runtime.d ================================================================== --- polemy/runtime.d +++ polemy/runtime.d @@ -20,31 +20,38 @@ class UndefinedValue : Value { mixin SimpleConstructor; mixin SimpleCompare; + override string toString() const { return "(undefined)"; } } class IntValue : Value { BigInt data; mixin SimpleConstructor; mixin SimpleCompare; + override string toString() const { + const(char)[] cs; data.toString((const(char)[] s){cs=s;}, null); + return to!string(cs); + } } class StrValue : Value { string data; mixin SimpleConstructor; mixin SimpleCompare; + override string toString() const { return data; } } class FunValue : Value { Value delegate(immutable LexPosition pos, Value[]) data; mixin SimpleConstructor; Value call(immutable LexPosition pos, Value[] args) { return data(pos,args); } + override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); } } import std.stdio; class Context { Context parent; Index: polemy/tricks.d ================================================================== --- polemy/tricks.d +++ polemy/tricks.d @@ -41,11 +41,11 @@ static if(this.tupleof.length>0) this.tupleof = params; } } -/// Mixing-in the (MOST-DERIVED) member-wise comparator for a class +/// Mixing-in the MOST-DERIVED-member-wise comparator for a class /*mixin*/ template SimpleCompare() { override bool opEquals(Object rhs_) const {