@@ -20,8 +20,9 @@ abstract class Value { } +/// class IntValue : Value { BigInt data; @@ -28,8 +29,9 @@ mixin SimpleClass; override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); } } +/// class StrValue : Value { string data; @@ -36,8 +38,9 @@ mixin SimpleClass; override string toString() const { return data; } } +/// class FunValue : Value { Value delegate(immutable LexPosition pos, string lay, Value[]) data; @@ -45,13 +48,45 @@ alias data call; override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); } } +/// class UndValue : Value { mixin SimpleClass; override string toString() const { return ""; } } + +/// Named Constructor for FunValue + +FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg) +{ + return new FunValue(dg); +} + +/// Named Constructor for FunValue + +FunValue native(R,T...)(R delegate (T) dg) +{ + return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) { + if( lay != "@v" ) + throw genex!RuntimeException(pos, "only @v layer can call native function"); + if( T.length != args.length ) + throw genex!RuntimeException(pos, "argument number mismatch!"); + T typed_args; + foreach(i, Ti; T) + { + typed_args[i] = cast(Ti) args[i]; + if( typed_args[i] is null ) + throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); + } + try { + return dg(typed_args); + } catch( RuntimeException e ) { + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; + } + }); +} /// Layer ID alias string Layer; @@ -73,11 +108,24 @@ return; data[i][lay] = v; } + bool has(string i, Layer lay, in LexPosition pos=null) + { + if( i in data ) { + if( lay !in data[i] ) + return false; + return true; + } + if( prototype is null ) + return false; + return prototype.has(i, lay, pos); + } + Value get(string i, Layer lay, in LexPosition pos=null) { if( i in data ) { + // [TODO] consider forwarding to proto also in this case if( lay !in data[i] ) throw genex!RuntimeException(pos, sprintf!"variable %s is not set in layer %s"(i,lay)); return data[i][lay]; }