Index: .poseidon
==================================================================
--- .poseidon
+++ .poseidon
@@ -34,12 +34,12 @@
polemy\_common.d
polemy\ast.d
polemy\eval.d
polemy\lex.d
polemy\parse.d
- polemy\runtime.d
polemy\tricks.d
+ polemy\value.d
Index: polemy/eval.d
==================================================================
--- polemy/eval.d
+++ polemy/eval.d
@@ -7,11 +7,11 @@
module polemy.eval;
import polemy._common;
import polemy.lex : LexPosition;
import polemy.ast;
import polemy.parse;
-import polemy.runtime;
+import polemy.value;
import std.typecons;
import std.stdio;
Context createGlobalContext()
{
DELETED polemy/runtime.d
Index: polemy/runtime.d
==================================================================
--- polemy/runtime.d
+++ polemy/runtime.d
@@ -1,82 +0,0 @@
-/**
- * Authors: k.inaba
- * License: NYSL 0.9982 http://www.kmonos.net/nysl/
- *
- * Runtime data structures for Polemy programming language.
- */
-module polemy.runtime;
-import polemy._common;
-import polemy.lex : LexPosition;
-import std.stdio;
-
-class PolemyRuntimeException : Exception
-{
- this(string msg) { super(msg); }
-}
-
-abstract class Value
-{
-}
-
-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 {
- return std.bigint.toDecimalString(cast(BigInt)data);
- }
-}
-
-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;
- Value[string] table;
- this(Context parent = null) { this.parent = parent; }
-
- void add(string i, Value v)
- {
- table[i] = v;
- }
-
- Value opIndex(string i)
- {
- if( i in table )
- return table[i];
- if( parent is null )
- throw new PolemyRuntimeException(sprintf!"variable %s not found"(i));
- return parent[i];
- }
-
- void opIndexAssign(Value v, string i)
- {
- if( i in table )
- return table[i] = v;
- if( parent is null )
- throw new PolemyRuntimeException(sprintf!"variable %s not found"(i));
- return parent[i] = v;
- }
-}
Index: polemy/tricks.d
==================================================================
--- polemy/tricks.d
+++ polemy/tricks.d
@@ -3,28 +3,69 @@
* License: NYSL 0.9982 http://www.kmonos.net/nysl/
*
* Common tricks and utilities for programming in D.
*/
module polemy.tricks;
-static import std.array;
-static import std.format;
-static import core.exception;
+import std.array : appender;
+import std.format : formattedWrite;
+import core.exception : onAssertErrorMsg, AssertError;
/// Simple Wrapper for std.format.doFormat
string sprintf(string fmt, T...)(T params)
{
- auto writer = std.array.appender!string();
- std.format.formattedWrite(writer, fmt, params);
+ auto writer = appender!string();
+ formattedWrite(writer, fmt, params);
return writer.data;
}
unittest
{
assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" );
assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" );
}
+
+/// Unittest helper that asserts an expression must throw something
+
+void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
+{
+ try {
+ t();
+ } catch(ExceptionType) {
+ return;
+ } catch(Throwable e) {
+ onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
+ }
+ onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption");
+}
+
+/// Unittest helper that asserts an expression must not throw anything
+
+void assert_nothrow(T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
+{
+ try {
+ t();
+ } catch(Throwable e) {
+ onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
+ }
+}
+
+unittest
+{
+ auto error = {throw new Error("hello");};
+ auto nothing = (){};
+ auto assertError = {assert(0);};
+
+ assert_nothrow ( assert_nothrow(nothing()) );
+ assert_throw!AssertError( assert_nothrow(error()) );
+ assert_throw!AssertError( assert_nothrow(assertError()) );
+
+ assert_nothrow ( assert_throw!Error(error()) );
+ assert_throw!AssertError( assert_throw!Error(nothing()) );
+ assert_nothrow ( assert_throw!Error(assertError()) );
+ assert_throw!AssertError( assert_throw!AssertError(error()) );
+}
/// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, >=
template assertOp(string op)
{
@@ -31,13 +72,13 @@
void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, string msg="")
{
try {
if( mixin("a"~op~"b") ) return;
} catch(Throwable e) {
- core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
+ onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
}
- core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b));
+ onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b));
}
}
alias assertOp!(`==`) assert_eq;
alias assertOp!(`!=`) assert_ne;
@@ -44,33 +85,34 @@
alias assertOp!(`<`) assert_lt;
alias assertOp!(`<=`) assert_le;
alias assertOp!(`>`) assert_gt;
alias assertOp!(`>=`) assert_ge;
-/// Unittest helper that asserts an expression must throw something
-
-void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
+unittest
{
- try {
- t();
- } catch(ExceptionType) {
- return;
- } catch(Throwable e) {
- core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
- }
- core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption");
-}
-
-/// Unittest helper that asserts an expression must not throw anything
-
-void assert_nothrow(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
-{
- try {
- t();
- } catch(Throwable e) {
- core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
- }
+ assert_nothrow( assert_eq("foo", "foo") );
+ assert_nothrow( assert_ne("foo", "bar") );
+ assert_nothrow( assert_lt("bar", "foo") );
+ assert_nothrow( assert_le("bar", "foo") );
+ assert_nothrow( assert_le("bar", "bar") );
+ assert_nothrow( assert_gt("foo", "bar") );
+ assert_nothrow( assert_ge("foo", "bar") );
+ assert_nothrow( assert_ge("bar", "bar") );
+
+ assert_throw!AssertError( assert_eq("foo", "bar") );
+ assert_throw!AssertError( assert_ne("foo", "foo") );
+ assert_throw!AssertError( assert_lt("foo", "foo") );
+ assert_throw!AssertError( assert_lt("foo", "bar") );
+ assert_throw!AssertError( assert_le("foo", "bar") );
+ assert_throw!AssertError( assert_gt("bar", "bar") );
+ assert_throw!AssertError( assert_gt("bar", "foo") );
+ assert_throw!AssertError( assert_ge("bar", "foo") );
+
+ class Temp { bool opEquals(int x){return x/x==x;} }
+ assert_throw!AssertError( assert_eq(new Temp, 0) );
+ assert_nothrow ( assert_eq(new Temp, 1) );
+ assert_throw!AssertError( assert_eq(new Temp, 2) );
}
/* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */
/// Mixing-in the bean constructor for a class
@@ -105,10 +147,30 @@
assert_eq( (new Temp(1,"foo")).x, 1 );
assert_eq( (new Temp(1,"foo")).y, "foo" );
assert( !__traits(compiles, new Temp) );
assert( !__traits(compiles, new Temp(1)) );
assert( !__traits(compiles, new Temp("foo",1)) );
+
+ class Tomp : Temp
+ {
+ real z;
+ mixin SimpleConstructor;
+ }
+ assert_eq( (new Tomp(1,"foo",2.5)).x, 1 );
+ assert_eq( (new Tomp(1,"foo",2.5)).y, "foo" );
+ assert_eq( (new Tomp(1,"foo",2.5)).z, 2.5 );
+ assert( !__traits(compiles, new Tomp(3.14)) );
+
+ // shiyo- desu. Don't use in this way.
+ // Tamp tries to call new Tomp(real) (because it only sees Tomp's members),
+ // but it fails because Tomp takes (int,string,real).
+ assert( !__traits(compiles, {
+ class Tamp : Tomp
+ {
+ mixin SimpleConstructor;
+ }
+ }) );
}
/// Mixing-in the MOST-DERIVED-member-wise comparator for a class
template SimpleCompare()
@@ -159,6 +221,17 @@
assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash );
assert_ne( new Temp(1,"foo"), new Temp(2,"foo") );
assert_ne( new Temp(1,"foo"), new Temp(1,"bar") );
assert_gt( new Temp(1,"foo"), new Temp(1,"bar") );
assert_lt( new Temp(1,"foo"), new Temp(2,"bar") );
+ assert_ge( new Temp(1,"foo"), new Temp(1,"foo") );
+
+ class TempDummy
+ {
+ int x;
+ string y;
+ mixin SimpleConstructor;
+ mixin SimpleCompare;
+ }
+ assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") );
+ assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") );
}
ADDED polemy/value.d
Index: polemy/value.d
==================================================================
--- polemy/value.d
+++ polemy/value.d
@@ -0,0 +1,82 @@
+/**
+ * Authors: k.inaba
+ * License: NYSL 0.9982 http://www.kmonos.net/nysl/
+ *
+ * Runtime data structures for Polemy programming language.
+ */
+module polemy.value;
+import polemy._common;
+import polemy.lex : LexPosition;
+import std.stdio;
+
+class PolemyRuntimeException : Exception
+{
+ this(string msg) { super(msg); }
+}
+
+abstract class Value
+{
+}
+
+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 {
+ return std.bigint.toDecimalString(cast(BigInt)data);
+ }
+}
+
+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;
+ Value[string] table;
+ this(Context parent = null) { this.parent = parent; }
+
+ void add(string i, Value v)
+ {
+ table[i] = v;
+ }
+
+ Value opIndex(string i)
+ {
+ if( i in table )
+ return table[i];
+ if( parent is null )
+ throw new PolemyRuntimeException(sprintf!"variable %s not found"(i));
+ return parent[i];
+ }
+
+ void opIndexAssign(Value v, string i)
+ {
+ if( i in table )
+ return table[i] = v;
+ if( parent is null )
+ throw new PolemyRuntimeException(sprintf!"variable %s not found"(i));
+ return parent[i] = v;
+ }
+}