Diff
Not logged in

Differences From Artifact [d315cdb0d9e5cf48]:

To Artifact [a63938dc88b0c424]:


8 8 import polemy._common; 9 9 import polemy.lex : LexPosition; 10 10 import polemy.ast; 11 11 import polemy.parse; 12 12 import polemy.value; 13 13 import std.typecons; 14 14 import std.stdio; 15 + 16 +// [todo] move to value.d 17 + 18 +FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg) 19 +{ 20 + return new FunValue(dg); 21 +} 22 + 23 +FunValue native(R,T...)(R delegate (T) dg) 24 +{ 25 + return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) { 26 + if( lay != "@v" ) 27 + throw genex!RuntimeException(pos, "only @v layer can call native function"); 28 + if( T.length != args.length ) 29 + throw genex!RuntimeException(pos, "argument number mismatch!"); 30 + T typed_args; 31 + foreach(i, Ti; T) 32 + { 33 + typed_args[i] = cast(Ti) args[i]; 34 + if( typed_args[i] is null ) 35 + throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i)); 36 + } 37 + try { 38 + return dg(typed_args); 39 + } catch( RuntimeException e ) { 40 + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; 41 + } 42 + }); 43 +} 15 44 16 45 /// 17 46 Table createGlobalContext() 18 47 { 19 48 auto ctx = new Table; 20 - // [TODO] autogenerate these typechecks 21 - ctx.set("+", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 22 - if( args.length != 2 ) 23 - throw genex!RuntimeException(pos, "+ takes two arguments!!"); 24 - if( auto x = cast(IntValue)args[0] ) 25 - if( auto y = cast(IntValue)args[1] ) 26 - return new IntValue(x.data+y.data); 27 - throw genex!RuntimeException(pos, "cannot add non-integers"); 28 - })); 29 - ctx.set("-", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 30 - if( args.length != 2 ) 31 - throw genex!RuntimeException(pos, "- takes two arguments!!"); 32 - if( auto x = cast(IntValue)args[0] ) 33 - if( auto y = cast(IntValue)args[1] ) 34 - return new IntValue(x.data-y.data); 35 - throw genex!RuntimeException(pos, "cannot subtract non-integers"); 36 - })); 37 - ctx.set("*", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 38 - if( args.length != 2 ) 39 - throw genex!RuntimeException(pos, "* takes two arguments!!"); 40 - if( auto x = cast(IntValue)args[0] ) 41 - if( auto y = cast(IntValue)args[1] ) 42 - return new IntValue(x.data*y.data); 43 - throw genex!RuntimeException(pos, "cannot multiply non-integers"); 44 - })); 45 - ctx.set("/", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 46 - if( args.length != 2 ) 47 - throw genex!RuntimeException(pos, "/ takes two arguments!!"); 48 - if( auto x = cast(IntValue)args[0] ) 49 - if( auto y = cast(IntValue)args[1] ) 50 - return new IntValue(x.data/y.data); 51 - throw genex!RuntimeException(pos, "cannot divide non-integers"); 52 - })); 53 - ctx.set("<", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 54 - if( args.length != 2 ) 55 - throw genex!RuntimeException(pos, "< takes two arguments!!"); 56 - if( auto x = cast(IntValue)args[0] ) 57 - if( auto y = cast(IntValue)args[1] ) 58 - return new IntValue(BigInt(to!int(x.data < y.data))); 59 - throw genex!RuntimeException(pos, "cannot compare non-integers"); 60 - })); 61 - ctx.set(">", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 62 - if( args.length != 2 ) 63 - throw genex!RuntimeException(pos, "> takes two arguments!!"); 64 - if( auto x = cast(IntValue)args[0] ) 65 - if( auto y = cast(IntValue)args[1] ) 66 - return new IntValue(BigInt(to!int(x.data>y.data))); 67 - throw genex!RuntimeException(pos, "cannot compare non-integers"); 68 - })); 49 + ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} )); 50 + ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} )); 51 + ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} )); 52 + ctx.set("/", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} )); 53 + ctx.set("%", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} )); 54 + ctx.set("<", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data < rhs.data ? 1: 0));} )); 55 + ctx.set(">", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data > rhs.data ? 1: 0));} )); 56 + ctx.set("<=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data <= rhs.data ? 1: 0));} )); 57 + ctx.set(">=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data >= rhs.data ? 1: 0));} )); 58 + ctx.set("==", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data == rhs.data ? 1: 0));} )); 59 + ctx.set("!=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data != rhs.data ? 1: 0));} )); 69 60 ctx.set("print", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 70 61 foreach(a; args) 71 62 write(a); 72 63 writeln(""); 73 64 return new IntValue(BigInt(178)); 74 65 })); 75 66 ctx.set("if", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ ................................................................................ 105 96 Table ctx = createGlobalContext(); 106 97 return typeof(return)(eval(e, ctx, false, "@v"), ctx); 107 98 } 108 99 109 100 /// Entry point of this module 110 101 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 111 102 /// lay is the layer ID for evaluation (standard value semantics uses "@v"). 112 -import std.typetuple; 103 + 113 104 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 114 105 { 115 106 return e.match( 116 107 (StrLiteral e) 117 108 { 118 109 Value v = new StrValue(e.data); 119 110 if( lay == "@v" ) 120 111 return v; 121 - else 112 + else // rise 122 113 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]); 123 114 }, 124 115 (IntLiteral e) 125 116 { 126 117 Value v = new IntValue(e.data); 127 118 if( lay == "@v" ) 128 119 return v; 129 - else // are these "@v"s appropriate??? 120 + else // rise 130 121 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]); 131 122 }, 132 123 (VarExpression e) 133 124 { 134 125 try { 135 126 return ctx.get(e.var, lay, e.pos); 136 127 } catch( RuntimeException ) { 137 - // rise 128 + // rise from @v 138 129 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", 139 130 [ctx.get(e.var, "@v", e.pos)] 140 131 ); 141 132 } 142 133 }, 143 134 (LayeredExpression e) 144 135 { ................................................................................ 163 154 args ~= eval(a, ctx, true, lay); 164 155 return f.call(e.pos, lay, args); 165 156 } 166 157 throw genex!RuntimeException(e.pos, "Non-funcion is applied"); 167 158 }, 168 159 (FunLiteral e) 169 160 { 161 + // funvalue need not be rised 170 162 return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){ 171 163 if( e.params.length != args.length ) 172 164 throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" 173 165 (e.params.length, args.length)); 174 166 Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); 175 167 foreach(i,p; e.params) 176 168 ctxNeo.set(p.name, lay, args[i]);