Check-in [435fa085ec]
Not logged in
Overview
SHA1 Hash:435fa085ecbb38915bc81b52b32ebad205055044
Date: 2010-11-21 18:53:17
User: kinaba
Comment:refactored predefined layer names, and filled readme.txt.
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [3a1ec7254a3a05f2] to [689f2a54d91081ce].

31 <name>d2stacktrace\dbghelp.d</name> 31 <name>d2stacktrace\dbghelp.d</name> 32 <name>d2stacktrace\stacktrace.d</name> 32 <name>d2stacktrace\stacktrace.d</name> 33 <name>main.d</name> 33 <name>main.d</name> 34 <name>polemy\_common.d</name> 34 <name>polemy\_common.d</name> 35 <name>polemy\ast.d</name> 35 <name>polemy\ast.d</name> 36 <name>polemy\eval.d</name> 36 <name>polemy\eval.d</name> 37 <name>polemy\failure.d</name> 37 <name>polemy\failure.d</name> > 38 <name>polemy\layer.d</name> 38 <name>polemy\lex.d</name> 39 <name>polemy\lex.d</name> 39 <name>polemy\parse.d</name> 40 <name>polemy\parse.d</name> 40 <name>polemy\value.d</name> 41 <name>polemy\value.d</name> 41 <name>tricks\test.d</name> 42 <name>tricks\test.d</name> 42 <name>tricks\tricks.d</name> 43 <name>tricks\tricks.d</name> 43 </source> 44 </source> 44 <interface /> 45 <interface />

Modified doc/candydoc/modules.ddoc from [16e1e2b29a0a959b] to [14742f81f6b8c11a].

1 MODULES = 1 MODULES = 2 $(MODULE main) 2 $(MODULE main) 3 $(MODULE tricks.tricks) 3 $(MODULE tricks.tricks) 4 $(MODULE tricks.test) 4 $(MODULE tricks.test) 5 $(MODULE polemy._common) 5 $(MODULE polemy._common) 6 $(MODULE polemy.failure) 6 $(MODULE polemy.failure) > 7 $(MODULE polemy.layer) 7 $(MODULE polemy.lex) 8 $(MODULE polemy.lex) 8 $(MODULE polemy.parse) 9 $(MODULE polemy.parse) 9 $(MODULE polemy.ast) 10 $(MODULE polemy.ast) 10 $(MODULE polemy.eval) 11 $(MODULE polemy.eval) 11 $(MODULE polemy.value) 12 $(MODULE polemy.value)

Modified main.d from [3594122dc7a67c3c] to [636370f08c051cf2].

9 import std.algorithm; 9 import std.algorithm; 10 import std.array; 10 import std.array; 11 import polemy.value; 11 import polemy.value; 12 import polemy.failure; 12 import polemy.failure; 13 import polemy.parse; 13 import polemy.parse; 14 import polemy.ast; 14 import polemy.ast; 15 import polemy.eval; 15 import polemy.eval; > 16 import polemy.layer; 16 17 17 enum VersionNoMajor = 0; 18 enum VersionNoMajor = 0; 18 enum VersionNoMinor = 1; 19 enum VersionNoMinor = 1; 19 enum VersionNoRev = 0; 20 enum VersionNoRev = 0; 20 21 21 /// Read-Eval-Print-Loop 22 /// Read-Eval-Print-Loop 22 23 ................................................................................................................................................................................ 33 { 34 { 34 writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNo 35 writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNo 35 } 36 } 36 37 37 /// Run one file on the global scope 38 /// Run one file on the global scope 38 void runFile(string filename) 39 void runFile(string filename) 39 { 40 { 40 eval(parseFile(filename), ctx, false, "@v"); | 41 eval(parseFile(filename), ctx, false, ValueLayer); 41 } 42 } 42 43 43 /// Repeat the singleInteraction 44 /// Repeat the singleInteraction 44 void replLoop() 45 void replLoop() 45 { 46 { 46 while( singleInteraction() ) {} 47 while( singleInteraction() ) {} 47 } 48 } ................................................................................................................................................................................ 73 { 74 { 74 scope(failure) 75 scope(failure) 75 { buf = ""; lineno = nextlineno; } 76 { buf = ""; lineno = nextlineno; } 76 77 77 buf ~= s; 78 buf ~= s; 78 nextlineno ++; 79 nextlineno ++; 79 try 80 try 80 { lastVal = eval(parseString(buf, "<REPL>", lineno), ctx | 81 { lastVal = eval(parseString(buf, "<REPL>", lineno), ctx 81 catch( UnexpectedEOF ) 82 catch( UnexpectedEOF ) 82 { return false; } // wait 83 { return false; } // wait 83 buf = ""; 84 buf = ""; 84 lineno = nextlineno; 85 lineno = nextlineno; 85 return true; 86 return true; 86 } 87 } 87 } 88 }

Modified polemy/eval.d from [27ad20bc14df9938] to [0e6e0e9d77fcbedc].

6 */ 6 */ 7 module polemy.eval; 7 module polemy.eval; 8 import polemy._common; 8 import polemy._common; 9 import polemy.failure; 9 import polemy.failure; 10 import polemy.ast; 10 import polemy.ast; 11 import polemy.parse; 11 import polemy.parse; 12 import polemy.value; 12 import polemy.value; > 13 import polemy.layer; 13 import std.typecons; 14 import std.typecons; 14 import std.stdio; 15 import std.stdio; 15 16 16 /// 17 /// 17 Table createGlobalContext() 18 Table createGlobalContext() 18 { 19 { 19 auto ctx = new Table; 20 auto ctx = new Table; 20 ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 21 ctx.set("+", ValueLayer, native( (IntValue lhs, IntValue rhs){return new 21 ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 22 ctx.set("-", ValueLayer, native( (IntValue lhs, IntValue rhs){return new 22 ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 23 ctx.set("*", ValueLayer, native( (IntValue lhs, IntValue rhs){return new 23 ctx.set("/", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 24 ctx.set("/", ValueLayer, native( (IntValue lhs, IntValue rhs){return new 24 ctx.set("%", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 25 ctx.set("%", ValueLayer, native( (IntValue lhs, IntValue rhs){return new 25 ctx.set("||", "@v", native( (IntValue lhs, IntValue rhs){return new IntV | 26 ctx.set("||", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne 26 ctx.set("&&", "@v", native( (IntValue lhs, IntValue rhs){return new IntV | 27 ctx.set("&&", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne 27 ctx.set("<", "@v", native( (Value lhs, Value rhs){return new IntValue(Bi | 28 ctx.set("<", ValueLayer, native( (Value lhs, Value rhs){return new IntVa 28 ctx.set(">", "@v", native( (Value lhs, Value rhs){return new IntValue(Bi | 29 ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntVa 29 ctx.set("<=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 30 ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntV 30 ctx.set(">=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 31 ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntV 31 ctx.set("==", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 32 ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntV 32 ctx.set("!=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 33 ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntV 33 ctx.set("print", "@v", native( (Value a){ | 34 ctx.set("print", ValueLayer, native( (Value a){ 34 writeln(a); 35 writeln(a); 35 return new IntValue(BigInt(178)); 36 return new IntValue(BigInt(178)); 36 })); 37 })); 37 ctx.set("if", "@v", native( (IntValue x, FunValue ft, FunValue fe){ | 38 ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe) 38 auto toRun = (x.data==0 ? fe : ft); 39 auto toRun = (x.data==0 ? fe : ft); 39 return toRun.invoke(null, "@v", toRun.definitionContext()); | 40 return toRun.invoke(null, ValueLayer, toRun.definitionContext()) 40 // return toRun.invoke(pos, lay, toRun.definitionContext()); 41 // return toRun.invoke(pos, lay, toRun.definitionContext()); 41 })); 42 })); 42 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cas | 43 ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigI 43 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cas | 44 ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigI 44 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cas | 45 ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigI 45 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigI | 46 ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValu 46 ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(c | 47 ctx.set("_istable", ValueLayer, native( (Value v){return new IntValue(Bi 47 ctx.set(".", "@v", native( (Table t, StrValue s){ | 48 ctx.set(".", ValueLayer, native( (Table t, StrValue s){ 48 return (t.has(s.data, "@v") ? t.get(s.data, "@v") : new UndValue | 49 return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : > 50 }) ); > 51 ctx.set(".?", ValueLayer, native( (Table t, StrValue s){ > 52 return new IntValue(BigInt(t.has(s.data, ValueLayer) ? 1 : 0)); 49 }) ); 53 }) ); 50 ctx.set(".?", "@v", native( (Table t, StrValue s){ < 51 return new IntValue(BigInt(t.has(s.data, "@v") ? 1 : 0)); < 52 }) ); < 53 ctx.set(".=", "@v", native( (Table t, StrValue s, Value v){ | 54 ctx.set(".=", ValueLayer, native( (Table t, StrValue s, Value v){ 54 auto t2 = new Table(t, Table.Kind.NotPropagateSet); 55 auto t2 = new Table(t, Table.Kind.NotPropagateSet); 55 t2.set(s.data, "@v", v); | 56 t2.set(s.data, ValueLayer, v); 56 return t2; 57 return t2; 57 }) ); 58 }) ); 58 ctx.set("{}", "@v", native( (){ | 59 ctx.set("{}", ValueLayer, native( (){ 59 return new Table; 60 return new Table; 60 }) ); 61 }) ); 61 return ctx; 62 return ctx; 62 } 63 } 63 64 64 /// Entry point of this module 65 /// Entry point of this module 65 66 ................................................................................................................................................................................ 76 } 77 } 77 78 78 /// Entry point of this module 79 /// Entry point of this module 79 80 80 Tuple!(Value,"val",Table,"ctx") eval(AST e) 81 Tuple!(Value,"val",Table,"ctx") eval(AST e) 81 { 82 { 82 Table ctx = createGlobalContext(); 83 Table ctx = createGlobalContext(); 83 return typeof(return)(eval(e, ctx, false, "@v"), ctx); | 84 return typeof(return)(eval(e, ctx, false, ValueLayer), ctx); 84 } 85 } 85 86 86 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, 87 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, 87 { 88 { 88 if(auto f = cast(FunValue)_f) 89 if(auto f = cast(FunValue)_f) 89 { 90 { 90 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 91 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 91 foreach(i,p; f.params()) 92 foreach(i,p; f.params()) 92 if( p.layers.empty ) 93 if( p.layers.empty ) 93 if(lay=="@macro") | 94 if(lay==MacroLayer) 94 ctx.set(p.name, lay, macroEval(args[i], 95 ctx.set(p.name, lay, macroEval(args[i], 95 else 96 else 96 ctx.set(p.name, lay, eval(args[i], calle 97 ctx.set(p.name, lay, eval(args[i], calle 97 else 98 else 98 foreach(argLay; p.layers) 99 foreach(argLay; p.layers) 99 if(argLay=="@macro") | 100 if(argLay==MacroLayer) 100 ctx.set(p.name, argLay, macroEva 101 ctx.set(p.name, argLay, macroEva 101 else 102 else 102 ctx.set(p.name, argLay, eval(arg 103 ctx.set(p.name, argLay, eval(arg 103 return f.invoke(pos, lay, ctx); 104 return f.invoke(pos, lay, ctx); 104 } 105 } 105 throw genex!RuntimeException(pos, "tried to call non-function"); 106 throw genex!RuntimeException(pos, "tried to call non-function"); 106 } 107 } 107 108 108 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) 109 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) 109 { 110 { 110 // similar to invoke Function, but with only one argument bound to @v | 111 // similar to invoke Function, but with only one argument bound to Value 111 Value _f = callerCtx.get(lay, "(system)", pos); | 112 Value _f = callerCtx.get(lay, SystemLayer, pos); 112 if(auto f = cast(FunValue)_f) 113 if(auto f = cast(FunValue)_f) 113 { 114 { 114 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 115 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 115 auto ps = f.params(); 116 auto ps = f.params(); 116 if( ps.length != 1 ) 117 if( ps.length != 1 ) 117 throw genex!RuntimeException(pos, "lift function must ta | 118 throw genex!RuntimeException(pos, "lift function must ta 118 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la | 119 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la 119 { 120 { 120 ctx.set(ps[0].name, "@v", v); | 121 ctx.set(ps[0].name, ValueLayer, v); 121 return f.invoke(pos, "@v", ctx); | 122 return f.invoke(pos, ValueLayer, ctx); 122 } 123 } 123 else 124 else 124 throw genex!RuntimeException(pos, "lift function must ta | 125 throw genex!RuntimeException(pos, "lift function must ta 125 } 126 } 126 throw genex!RuntimeException(pos, "tried to call non-function"); 127 throw genex!RuntimeException(pos, "tried to call non-function"); 127 } 128 } 128 129 129 /// Entry point of this module 130 /// Entry point of this module 130 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 131 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 131 /// lay is the layer ID for evaluation (standard value semantics uses "@v"). | 132 /// lay is the layer ID for evaluation (standard value semantics uses ValueLayer 132 133 133 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 134 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 134 { 135 { 135 return e.match( 136 return e.match( 136 (StrLiteral e) 137 (StrLiteral e) 137 { 138 { 138 Value v = new StrValue(e.data); 139 Value v = new StrValue(e.data); 139 if( lay == "@v" ) | 140 if( lay == ValueLayer ) 140 return v; 141 return v; 141 else 142 else 142 return lift(e.pos,v,lay,ctx); 143 return lift(e.pos,v,lay,ctx); 143 }, 144 }, 144 (IntLiteral e) 145 (IntLiteral e) 145 { 146 { 146 Value v = new IntValue(e.data); 147 Value v = new IntValue(e.data); 147 if( lay == "@v" ) | 148 if( lay == ValueLayer ) 148 return v; 149 return v; 149 else // rise 150 else // rise 150 return lift(e.pos,v,lay,ctx); 151 return lift(e.pos,v,lay,ctx); 151 }, 152 }, 152 (VarExpression e) 153 (VarExpression e) 153 { 154 { 154 if( lay == "@v" ) | 155 if( lay == ValueLayer ) 155 return ctx.get(e.var, lay, e.pos); 156 return ctx.get(e.var, lay, e.pos); 156 try { 157 try { 157 return ctx.get(e.var, lay, e.pos); 158 return ctx.get(e.var, lay, e.pos); 158 } catch( Throwable ) { // [TODO] more precise... 159 } catch( Throwable ) { // [TODO] more precise... 159 return lift(e.pos, ctx.get(e.var, "@v", e.pos), | 160 return lift(e.pos, ctx.get(e.var, ValueLayer, e. 160 } 161 } 161 }, 162 }, 162 (LayeredExpression e) 163 (LayeredExpression e) 163 { 164 { 164 if( e.lay == "@macro" ) | 165 if( e.lay == MacroLayer ) 165 return macroEval(e.expr, ctx, false); 166 return macroEval(e.expr, ctx, false); 166 else 167 else 167 return eval(e.expr, ctx, true, e.lay); 168 return eval(e.expr, ctx, true, e.lay); 168 }, 169 }, 169 (LetExpression e) 170 (LetExpression e) 170 { 171 { 171 // for letrec, we need this, but should avoid overwritin 172 // for letrec, we need this, but should avoid overwritin 172 // ctx.set(e.var, "@v", new UndefinedValue, e.pos); | 173 // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos) 173 if(splitCtx) 174 if(splitCtx) 174 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 175 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 175 Value v = eval(e.init, ctx, true, lay); 176 Value v = eval(e.init, ctx, true, lay); 176 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.po 177 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.po 177 return eval(e.expr, ctx, false, lay); 178 return eval(e.expr, ctx, false, lay); 178 }, 179 }, 179 (FuncallExpression e) 180 (FuncallExpression e) ................................................................................................................................................................................ 195 } 196 } 196 ); 197 ); 197 } 198 } 198 199 199 // [TODO] Optimization 200 // [TODO] Optimization 200 Value macroEval(AST e, Table ctx, bool AlwaysMacro) 201 Value macroEval(AST e, Table ctx, bool AlwaysMacro) 201 { 202 { 202 Layer theLayer = "@v"; | 203 Layer theLayer = ValueLayer; 203 204 204 Table pos = new Table; 205 Table pos = new Table; 205 pos.set("filename", theLayer, new StrValue(e.pos.filename)); 206 pos.set("filename", theLayer, new StrValue(e.pos.filename)); 206 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 207 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 207 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 208 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 208 return e.match( 209 return e.match( 209 (StrLiteral e) 210 (StrLiteral e) ................................................................................................................................................................................ 221 t.set("is", theLayer, new StrValue("int")); 222 t.set("is", theLayer, new StrValue("int")); 222 t.set("data", theLayer, new IntValue(e.data)); 223 t.set("data", theLayer, new IntValue(e.data)); 223 return t; 224 return t; 224 }, 225 }, 225 (VarExpression e) 226 (VarExpression e) 226 { 227 { 227 try { 228 try { 228 return ctx.get(e.var, "@macro", e.pos); | 229 return ctx.get(e.var, MacroLayer, e.pos); 229 } catch( Throwable ) {// [TODO] more precies... 230 } catch( Throwable ) {// [TODO] more precies... 230 Table t = new Table; 231 Table t = new Table; 231 t.set("pos", theLayer, pos); 232 t.set("pos", theLayer, pos); 232 t.set("is", theLayer, new StrValue("var")); 233 t.set("is", theLayer, new StrValue("var")); 233 t.set("name", theLayer, new StrValue(e.var)); 234 t.set("name", theLayer, new StrValue(e.var)); 234 return cast(Value)t; 235 return cast(Value)t; 235 } 236 } ................................................................................................................................................................................ 243 t.set("is", theLayer, new StrValue("lay")); 244 t.set("is", theLayer, new StrValue("lay")); 244 t.set("layer", theLayer, new StrValue(e.lay)); 245 t.set("layer", theLayer, new StrValue(e.lay)); 245 t.set("expr", theLayer, macroEval(e.expr,ctx,Alw 246 t.set("expr", theLayer, macroEval(e.expr,ctx,Alw 246 return cast(Value)t; 247 return cast(Value)t; 247 } 248 } 248 else 249 else 249 { 250 { 250 if( e.lay == "@macro" ) | 251 if( e.lay == MacroLayer ) 251 return macroEval(e.expr, ctx, false); 252 return macroEval(e.expr, ctx, false); 252 else 253 else 253 return eval(e.expr, ctx, true, e.lay); 254 return eval(e.expr, ctx, true, e.lay); 254 } 255 } 255 }, 256 }, 256 (LetExpression e) 257 (LetExpression e) 257 { 258 { ................................................................................................................................................................................ 264 return t; 265 return t; 265 }, 266 }, 266 (FuncallExpression e) 267 (FuncallExpression e) 267 { 268 { 268 Value _f = macroEval(e.fun,ctx,AlwaysMacro); 269 Value _f = macroEval(e.fun,ctx,AlwaysMacro); 269 270 270 if( auto f = cast(FunValue)_f ) 271 if( auto f = cast(FunValue)_f ) 271 return invokeFunction(e.pos, f, e.args, ctx, "@m | 272 return invokeFunction(e.pos, f, e.args, ctx, Mac 272 273 273 Table t = new Table; 274 Table t = new Table; 274 t.set("pos", theLayer, pos); 275 t.set("pos", theLayer, pos); 275 t.set("is", theLayer, new StrValue("app")); 276 t.set("is", theLayer, new StrValue("app")); 276 t.set("fun", theLayer, _f); 277 t.set("fun", theLayer, _f); 277 Table args = new Table; 278 Table args = new Table; 278 foreach_reverse(a; e.args) { 279 foreach_reverse(a; e.args) { ................................................................................................................................................................................ 317 ); 318 ); 318 } 319 } 319 320 320 unittest 321 unittest 321 { 322 { 322 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); 323 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); 323 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 324 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 324 assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21)) ); | 325 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21)) ); 325 assert_nothrow( r.ctx.get("x","@v") ); | 326 assert_nothrow( r.ctx.get("x",ValueLayer) ); 326 assert_throw!RuntimeException( r.ctx.get("y","@v") ); | 327 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); 327 } 328 } 328 unittest 329 unittest 329 { 330 { 330 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); 331 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); 331 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 332 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 332 assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21+21*21)) ); | 333 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) ); 333 assert_nothrow( r.ctx.get("x","@v") ); | 334 assert_nothrow( r.ctx.get("x",ValueLayer) ); 334 assert_throw!RuntimeException( r.ctx.get("y","@v") ); | 335 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); 335 } 336 } 336 unittest 337 unittest 337 { 338 { 338 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B 339 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B 339 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new 340 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new 340 } 341 } 341 unittest 342 unittest ................................................................................................................................................................................ 364 fib(5);`).val, new IntValue(BigInt(8))); 365 fib(5);`).val, new IntValue(BigInt(8))); 365 } 366 } 366 367 367 unittest 368 unittest 368 { 369 { 369 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1 370 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1 370 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In 371 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In 371 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};1+2`) | 372 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};1 372 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};@s(1+ | 373 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};@ 373 } 374 } 374 375 375 unittest 376 unittest 376 { 377 { 377 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 378 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 378 // there was a bug that declaration in the first line of function defini 379 // there was a bug that declaration in the first line of function defini 379 // cannot be recursive 380 // cannot be recursive 380 assert_nothrow( evalString(`def foo() { 381 assert_nothrow( evalString(`def foo() { 381 def bar(y) { if(y<1) {0} else {bar(0)} }; 382 def bar(y) { if(y<1) {0} else {bar(0)} }; 382 bar(1) 383 bar(1) 383 }; foo()`) ); 384 }; foo()`) ); 384 } 385 } 385 <

Modified polemy/parse.d from [25ec86a59533b939] to [71d187282fb3ce05].

5 * Parser for Polemy programming language 5 * Parser for Polemy programming language 6 */ 6 */ 7 module polemy.parse; 7 module polemy.parse; 8 import polemy._common; 8 import polemy._common; 9 import polemy.failure; 9 import polemy.failure; 10 import polemy.lex; 10 import polemy.lex; 11 import polemy.ast; 11 import polemy.ast; > 12 import polemy.layer; 12 13 13 /// Parse a string and return its AST 14 /// Parse a string and return its AST 14 /// Throws: ParseException, LexException, UnexpectedEOF 15 /// Throws: ParseException, LexException, UnexpectedEOF 15 16 16 AST parseString(S, T...)(S str, T fn_ln_cn) 17 AST parseString(S, T...)(S str, T fn_ln_cn) 17 { 18 { 18 return parserFromString(str, fn_ln_cn).parse(); 19 return parserFromString(str, fn_ln_cn).parse(); ................................................................................................................................................................................ 98 string kwd = "@" ~ layer; 99 string kwd = "@" ~ layer; 99 string var = layer; 100 string var = layer; 100 101 101 auto e = tryEat("(") 102 auto e = tryEat("(") 102 ? parseLambdaAfterOpenParen(pos) // let var ( . 103 ? parseLambdaAfterOpenParen(pos) // let var ( . 103 : (eat("=", "after "~kwd), E(0)); // let var = . 104 : (eat("=", "after "~kwd), E(0)); // let var = . 104 if( moreDeclarationExists() ) 105 if( moreDeclarationExists() ) 105 return new LetExpression(pos, var, "(system)", e | 106 return new LetExpression(pos, var, SystemLayer, 106 else 107 else 107 return new LetExpression(pos, var, "(system)", e | 108 return new LetExpression(pos, var, SystemLayer, 108 } 109 } 109 else 110 else 110 { 111 { 111 string kwd = layer; 112 string kwd = layer; 112 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 113 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 113 return null; // none of {@lay, let, var, def} oc 114 return null; // none of {@lay, let, var, def} oc 114 115 ................................................................................................................................................................................ 471 assert_eq(parseString(`def foo(x) { x+1 }; foo`), 472 assert_eq(parseString(`def foo(x) { x+1 }; foo`), 472 let("foo", "", 473 let("foo", "", 473 fun(["x"], call(var("+"), var("x"), intl(1))), 474 fun(["x"], call(var("+"), var("x"), intl(1))), 474 var("foo")) 475 var("foo")) 475 ); 476 ); 476 477 477 assert_eq(parseString(`@@type ( x ) { x }`), 478 assert_eq(parseString(`@@type ( x ) { x }`), 478 let("@type", "(system)", fun(["x"], var("x")), var("@type")) ); | 479 let("@type", SystemLayer, fun(["x"], var("x")), var("@type")) ); 479 480 480 assert_eq(parseString(`{}`), call(var("{}"))); 481 assert_eq(parseString(`{}`), call(var("{}"))); 481 assert_eq(parseString(`{foo:1,"bar":2}`), 482 assert_eq(parseString(`{foo:1,"bar":2}`), 482 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), in 483 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), in 483 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo 484 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo 484 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("f 485 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("f 485 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl( 486 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl( 486 } 487 }

Modified polemy/value.d from [f1a01bb8ba2daf26] to [57b0a5dd9a9946f6].

4 * 4 * 5 * Runtime data structures for Polemy programming language. 5 * Runtime data structures for Polemy programming language. 6 */ 6 */ 7 module polemy.value; 7 module polemy.value; 8 import polemy._common; 8 import polemy._common; 9 import polemy.failure; 9 import polemy.failure; 10 import polemy.ast; 10 import polemy.ast; > 11 import polemy.layer; 11 12 12 /// Runtime values of Polemy 13 /// Runtime values of Polemy 13 14 14 abstract class Value 15 abstract class Value 15 { 16 { 16 } 17 } 17 18 ................................................................................................................................................................................ 59 override const(Parameter[]) params() { return ast.params; } 60 override const(Parameter[]) params() { return ast.params; } 60 override Table definitionContext() { return defCtx; } 61 override Table definitionContext() { return defCtx; } 61 override Value invoke(in LexPosition pos, Layer lay, Table ctx) 62 override Value invoke(in LexPosition pos, Layer lay, Table ctx) 62 { 63 { 63 // TODO: only auto raised ones need memo? no? 64 // TODO: only auto raised ones need memo? no? 64 // auto memoization 65 // auto memoization 65 /* 66 /* 66 if( lay != "@v" && lay != "@macro" ) | 67 if( lay != ValueLayer && lay != MacroLayer ) 67 { 68 { 68 if( auto memolay = lay in memo ) 69 if( auto memolay = lay in memo ) 69 if( auto pv = args in *memolay ) 70 if( auto pv = args in *memolay ) 70 return *pv; 71 return *pv; 71 memo[lay][args] = lift(e.pos,new UndValue,lay,ctx); 72 memo[lay][args] = lift(e.pos,new UndValue,lay,ctx); 72 } 73 } 73 74 74 */ 75 */ 75 // @macro run!!! 76 // @macro run!!! 76 if( lay == "@macro" ) | 77 if( lay == MacroLayer ) 77 return macroEval(ast.funbody, ctx, false); 78 return macroEval(ast.funbody, ctx, false); 78 /*TODO memo*/ AST macroMemo; 79 /*TODO memo*/ AST macroMemo; 79 if( macroMemo is null ) { 80 if( macroMemo is null ) { 80 // .prototype!, forced macro cannot access parameters 81 // .prototype!, forced macro cannot access parameters 81 ctx.kill = true; scope(exit)ctx.kill=false; 82 ctx.kill = true; scope(exit)ctx.kill=false; 82 macroMemo = tableToAST("@v",macroEval(ast.funbody, ctx, | 83 macroMemo = tableToAST(ValueLayer,macroEval(ast.funbody, 83 } 84 } 84 auto v = eval(macroMemo, ctx, true, lay); 85 auto v = eval(macroMemo, ctx, true, lay); 85 86 86 //auto v = eval(e.funbody, ctxNeo, true, lay); 87 //auto v = eval(e.funbody, ctxNeo, true, lay); 87 // auto memoization 88 // auto memoization 88 // if( lay != "@v" && lay != "@macro" ) | 89 // if( lay != ValueLayer && lay != MacroLayer ) 89 // memo[lay][args] = v; 90 // memo[lay][args] = v; 90 return v; 91 return v; 91 } 92 } 92 93 93 mixin SimpleClass; 94 mixin SimpleClass; 94 override string toString() const { return sprintf!"(function:%x:%x)"(cas 95 override string toString() const { return sprintf!"(function:%x:%x)"(cas 95 } 96 } ................................................................................................................................................................................ 110 this() 111 this() 111 { 112 { 112 foreach(i, Ti; T) 113 foreach(i, Ti; T) 113 params_data ~= new Parameter(text(i), []); 114 params_data ~= new Parameter(text(i), []); 114 } 115 } 115 override Value invoke(in LexPosition pos, Layer lay, Table ctx) 116 override Value invoke(in LexPosition pos, Layer lay, Table ctx) 116 { 117 { 117 if( lay != "@v" ) | 118 if( lay != ValueLayer ) 118 throw genex!RuntimeException(pos, "only @v layer | 119 throw genex!RuntimeException(pos, "only "~ValueL 119 T typed_args; 120 T typed_args; 120 foreach(i, Ti; T) { 121 foreach(i, Ti; T) { 121 typed_args[i] = cast(Ti) ctx.get(text(i), "@v"); | 122 typed_args[i] = cast(Ti) ctx.get(text(i), ValueL 122 if( typed_args[i] is null ) 123 if( typed_args[i] is null ) 123 throw genex!RuntimeException(pos, sprint 124 throw genex!RuntimeException(pos, sprint 124 } 125 } 125 try { 126 try { 126 return dg(typed_args); 127 return dg(typed_args); 127 } catch( RuntimeException e ) { 128 } catch( RuntimeException e ) { 128 throw e.pos is null ? new RuntimeException(pos, 129 throw e.pos is null ? new RuntimeException(pos, 129 } 130 } 130 } 131 } 131 }; 132 }; 132 } 133 } 133 134 134 /// Layer ID < 135 < 136 alias string Layer; < 137 < 138 /// Context (variable environment) 135 /// Context (variable environment) 139 /// Simlar to prototype chain of ECMAScript etc. 136 /// Simlar to prototype chain of ECMAScript etc. 140 /// But extended with the notion of "Layer" 137 /// But extended with the notion of "Layer" 141 138 142 class Table : Value 139 class Table : Value 143 { 140 { 144 enum Kind {PropagateSet, NotPropagateSet}; 141 enum Kind {PropagateSet, NotPropagateSet}; ................................................................................................................................................................................ 245 unittest 242 unittest 246 { 243 { 247 Table c0 = new Table; 244 Table c0 = new Table; 248 Table c01 = new Table(c0, Table.Kind.NotPropagateSet); 245 Table c01 = new Table(c0, Table.Kind.NotPropagateSet); 249 Table c012 = new Table(c01, Table.Kind.PropagateSet); 246 Table c012 = new Table(c01, Table.Kind.PropagateSet); 250 Table c013 = new Table(c01, Table.Kind.PropagateSet); 247 Table c013 = new Table(c01, Table.Kind.PropagateSet); 251 248 252 assert_nothrow( c012.set("x", "@v", new IntValue(BigInt(12))) ); | 249 assert_nothrow( c012.set("x", ValueLayer, new IntValue(BigInt(12))) ); 253 assert_throw!RuntimeException( c013.get("x", "@v") ); | 250 assert_throw!RuntimeException( c013.get("x", ValueLayer) ); 254 assert_nothrow( c013.set("x", "@v", new IntValue(BigInt(13))) ); | 251 assert_nothrow( c013.set("x", ValueLayer, new IntValue(BigInt(13))) ); 255 assert_eq( c013.get("x", "@v"), new IntValue(BigInt(13)) ); | 252 assert_eq( c013.get("x", ValueLayer), new IntValue(BigInt(13)) ); 256 assert_eq( c012.get("x", "@v"), new IntValue(BigInt(12)) ); | 253 assert_eq( c012.get("x", ValueLayer), new IntValue(BigInt(12)) ); 257 assert_throw!RuntimeException( c01.get("x", "@v") ); | 254 assert_throw!RuntimeException( c01.get("x", ValueLayer) ); > 255 > 256 assert_nothrow( c01.set("y", ValueLayer, new IntValue(BigInt(1))) ); > 257 assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(1)) ); > 258 assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(1)) ); > 259 assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(1)) ); 258 260 259 assert_nothrow( c01.set("y", "@v", new IntValue(BigInt(1))) ); | 261 assert_nothrow( c0.set("z", ValueLayer, new IntValue(BigInt(0))) ); 260 assert_eq( c013.get("y", "@v"), new IntValue(BigInt(1)) ); | 262 assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); > 263 assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(0)) ); 261 assert_eq( c012.get("y", "@v"), new IntValue(BigInt(1)) ); | 264 assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 262 assert_eq( c01.get("y", "@v"), new IntValue(BigInt(1)) ); | 265 assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); 263 266 264 assert_nothrow( c0.set("z", "@v", new IntValue(BigInt(0))) ); < 265 assert_eq( c013.get("z", "@v"), new IntValue(BigInt(0)) ); | 267 assert_nothrow( c012.set("y", ValueLayer, new IntValue(BigInt(444))) ); 266 assert_eq( c012.get("z", "@v"), new IntValue(BigInt(0)) ); | 268 assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(444)) ); 267 assert_eq( c01.get("z", "@v"), new IntValue(BigInt(0)) ); | 269 assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(444)) ); 268 assert_eq( c0.get("z", "@v"), new IntValue(BigInt(0)) ); | 270 assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(444)) ); 269 271 270 assert_nothrow( c012.set("y", "@v", new IntValue(BigInt(444))) ); < 271 assert_eq( c013.get("y", "@v"), new IntValue(BigInt(444)) ); < 272 assert_eq( c012.get("y", "@v"), new IntValue(BigInt(444)) ); < 273 assert_eq( c01.get("y", "@v"), new IntValue(BigInt(444)) ); < 274 < 275 assert_nothrow( c012.set("z", "@v", new IntValue(BigInt(555))) ); | 272 assert_nothrow( c012.set("z", ValueLayer, new IntValue(BigInt(555))) ); 276 assert_eq( c013.get("z", "@v"), new IntValue(BigInt(0)) ); | 273 assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 277 assert_eq( c012.get("z", "@v"), new IntValue(BigInt(555)) ); | 274 assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) ); 278 assert_eq( c01.get("z", "@v"), new IntValue(BigInt(0)) ); | 275 assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 279 assert_eq( c0.get("z", "@v"), new IntValue(BigInt(0)) ); | 276 assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); 280 277 281 // [TODO] define the semantics and test @layers 278 // [TODO] define the semantics and test @layers 282 } 279 } 283 280 284 immutable(LexPosition) extractPos( Table t ) 281 immutable(LexPosition) extractPos( Table t ) 285 { 282 { 286 Layer theLayer = "@v"; | 283 Layer theLayer = ValueLayer; 287 if(auto tt = t.access!Table(theLayer, "pos")) 284 if(auto tt = t.access!Table(theLayer, "pos")) 288 { 285 { 289 auto fn = tt.access!StrValue(theLayer, "filename"); 286 auto fn = tt.access!StrValue(theLayer, "filename"); 290 auto ln = tt.access!IntValue(theLayer, "lineno"); 287 auto ln = tt.access!IntValue(theLayer, "lineno"); 291 auto cl = tt.access!IntValue(theLayer, "column"); 288 auto cl = tt.access!IntValue(theLayer, "column"); 292 if(fn !is null && ln !is null && cl !is null) 289 if(fn !is null && ln !is null && cl !is null) 293 return new immutable(LexPosition)(fn.data,cast(int)ln.da 290 return new immutable(LexPosition)(fn.data,cast(int)ln.da

Modified readme.txt from [6629940451babbd3] to [adcd1590f6f5bc80].

64 | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 64 | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 65 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 65 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 66 | ("var"|"let"|"def"|LAYER) ID "=" E 66 | ("var"|"let"|"def"|LAYER) ID "=" E 67 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 67 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 68 // literal 68 // literal 69 | INTEGER 69 | INTEGER 70 | STRING 70 | STRING 71 | "{" ENTRYS "}" | 71 | "{" ENTRYS "}" // table 72 | "fun" "(" PARAMS ")" "{" E "}" | 72 | "fun" "(" PARAMS ")" "{" E "}" // anonymous function 73 // function call 73 // function call 74 | E "(" ARGS")" 74 | E "(" ARGS")" 75 where ARGS ::= E "," ... "," E 75 where ARGS ::= E "," ... "," E 76 PARAMS ::= ID LAYER* "," ... "," ID LAYER* 76 PARAMS ::= ID LAYER* "," ... "," ID LAYER* 77 ENTRYS ::= ID ":" E "," ... "," ID ":" E 77 ENTRYS ::= ID ":" E "," ... "," ID ":" E 78 ID ::= 'a-zA-Z0-9_...'+ 78 ID ::= 'a-zA-Z0-9_...'+ 79 LAYER ::= "@" ID 79 LAYER ::= "@" ID 80 // operators 80 // operators 81 | "(" E ")" 81 | "(" E ")" 82 | E "." ID | 82 | E "." ID // table field access 83 | E ".?" ID | 83 | E ".?" ID // table field existence check > 84 | E "{" ENTRYS "}" // table extend (pure functionally) 84 | E BINOP E 85 | E BINOP E 85 | "if" "(" E ")" "{" E "}" 86 | "if" "(" E ")" "{" E "}" 86 | "if" "(" E ")" "{" E "}" "else "{" E "}" 87 | "if" "(" E ")" "{" E "}" "else "{" E "}" 87 // layered exec 88 // layered exec 88 | LAYER "(" E ")" 89 | LAYER "(" E ")" 89 90 90 The following are actually rewritten to function calls: 91 The following are actually rewritten to function calls: 91 92 92 - if (E) then{E} else{E} ==> if( E, fun(){E}, fun(){E} ) 93 - if (E) then{E} else{E} ==> if( E, fun(){E}, fun(){E} ) 93 - E BINOP E ==> BINOP(E, E) 94 - E BINOP E ==> BINOP(E, E) 94 - E.ID ==> . (E, ID) 95 - E.ID ==> . (E, ID) 95 - E.?ID ==> .?(E, ID) 96 - E.?ID ==> .?(E, ID) 96 - {} ==> {}() 97 - {} ==> {}() > 98 - { ENTRIES } ==> {}{ ENTRIES } 97 - {ID:E, ...} ==> .=({...}, ID, E) | 99 - E {ID:E, ...} ==> (.=(E, ID, E)) { ... } 98 100 99 Several styles of variable declaration can be used: 101 Several styles of variable declaration can be used: 100 102 101 - fun(x){ fun(y){x} } # K-combinator 103 - fun(x){ fun(y){x} } # K-combinator 102 - fun(x){ let f = fun(y){x} in f } # let-in style 104 - fun(x){ let f = fun(y){x} in f } # let-in style 103 - fun(x){ var f = fun(y){x}; f } # var-; style 105 - fun(x){ var f = fun(y){x}; f } # var-; style 104 - fun(x){ def f = fun(y){x} in f } # you can use any combination of (let|var| 106 - fun(x){ def f = fun(y){x} in f } # you can use any combination of (let|var| ................................................................................................................................................................................ 125 - tables: {car: 1, cdr: {car: 2, cdr: {}}} 127 - tables: {car: 1, cdr: {car: 2, cdr: {}}} 126 - functions: fun(x){x+1} 128 - functions: fun(x){x+1} 127 as primitive datatypes. Functions capture lexical closures. 129 as primitive datatypes. Functions capture lexical closures. 128 It is almost 'pure' (except the primitve function "print" and some 130 It is almost 'pure' (except the primitve function "print" and some 129 trick inside scoping mechanisms). 131 trick inside scoping mechanisms). 130 132 131 133 > 134 <<Layers :: Overview>> > 135 > 136 Polemy's runtime environment has many "layer"s. > 137 Usual execution run in the @value layer. > 138 > 139 >> 1 + 2 > 140 3 > 141 >> @value( 1 + 2 ) > 142 3 > 143 > 144 Here you can see that @LayerName( Expression ) executes the inner Expression i > 145 the @LayerName layer. Other than @value, one other predefined layer exists: @m > 146 > 147 >> @macro( 1+2 ) > 148 {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, > 149 is@value:app, > 150 arg@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@v > 151 is@value:int, > 152 data@value:1}, > 153 cdr@value:{ > 154 car@value:{pos@value:{lineno@value:3, column@value:11, filenam > 155 is@value:int, > 156 data@value:2}, > 157 cdr@value:{}}}, > 158 fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL > 159 is@value:var, > 160 name@value:+}} > 161 > 162 (Sorry, this pretty printing is not available on the actual interpreter...) > 163 This evaluates the expression 1+2 in the @macro layer. In this layer, the mean > 164 the program is its abstract syntax tree. > 165 > 166 You can interleave layers. > 167 The root node of the abstract syntax tree is function "app"lication. > 168 > 169 >> @value(@macro( 1+2 ).is) > 170 app > 171 > 172 > 173 > 174 <<Layers :: Defining a new layer>> > 175 > 176 To define a new layer, you should first tell how to "lift" existing values two > 177 Let us define the "@type" layer, where the meaning of programs is their static > 178 > 179 >> @@type = fun(x) { > 180 >> if( _isint(x) ) { "int" } else { > 181 >> if( _isfun(x) ) { x } else { "unknown" } } > 182 >> } > 183 (Note: polemy REPL may warn some exception here but please ignore) > 184 > 185 For simplicity, I here deal only with integers. > 186 _isint is a primitive function of Polemy that checks the dynamic type of a val > 187 For function, leaving it untouched works well for almost all layers. > 188 > 189 >> @type( 1 ) > 190 int > 191 >> @type( 2 ) > 192 int > 193 >> @type( "foo" ) > 194 unknown > 195 > 196 Fine! Let's try to type 1+2. > 197 > 198 >> @type( 1 + 2 ) > 199 ...\value.d(119): [<REPL>:6:8] only @value layer can call native function > 200 > 201 Note that the behavior of this program is > 202 - run 1+2 in the @type layer > 203 and NOT > 204 - run 1+2 in @value and obtain 3 and run 3 in the @type. > 205 The problem is, the variable "+" is defined only in the @value layer. > 206 To carry out computation in the @type layer. We need to define it also > 207 in the @type layer. > 208 > 209 To define some variable in a specific layer, use @LayerName in place of > 210 (let|var|def)s. > 211 > 212 >> let x = 2 > 213 >> @value x = 2 > 214 >> @type x = "int" > 215 >> @hoge x = "fuga" > 216 > 217 For "+", do it like this. > 218 > 219 >> @type "+" = fun(x,y) {@value( > 220 >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } > 221 >> )} > 222 polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 > 223 > 224 It is just computing the return type from the input type. > 225 Not here that the intended "meaning" of if-then-else is the runtime-branching, > 226 and the meaning of "==" is the value-comparison. These are the @value layer > 227 behavior. So we have defined the function body inside @value layer. > 228 But when we refer the variables x and y, we need its @type layer meaning. > 229 Hence we use @type() there. > 230 > 231 Now we get it. > 232 > 233 >> @type( 1 + 2 ) > 234 int > 235 > 236 Well, but do we have to define the @type layer meaning for every variables??? > 237 No. After you defined @type "+", you'll automatically get the following: > 238 > 239 >> def double(x) { x + x } > 240 (function:17e4740:1789720) > 241 > 242 >> @type( double(123) ) > 243 int > 244 > 245 Every user-defined functions are automatically "lift"ed to the appropriate lay > 246 Only primitive functions like "+" requires @yourNewLayer annotation. > 247 > 248 > 249 > 250 <<Layers :: neutral-layer>> > 251 > 252 let|var|def is to define a variable in the "current" layer. > 253 Not necessary to the @value layer. > 254 > 255 >> @value( let x = 1 in @value(x) ) > 256 1 > 257 > 258 >> @macro( let x = 1 in @value(x) ) > 259 polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found > 260 > 261 >> @macro( let x = 1 in @macro(x) ) > 262 {pos@value:{lineno@value:15, ... > 263 > 264 > 265 > 266 <<Layers :: Layered-Parameters>> > 267 > 268 >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } > 269 (function:1730360:1789720) > 270 > 271 If you annotate function parameters by @LayerNames, when you invoke the functi > 272 > 273 >> foo(1+2) > 274 {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REP > 275 is@value:app, arg@value:{... > 276 /fst@value:3 > 277 /} > 278 > 279 its corresponding arguments are evaluated in the layer and passed to it. > 280 If you specify multiple layers, the argument expression is run multiple times. > 281 If you do not specify any layer for a parameter, it works in the neutral layer > 282 > 283 > 284 132 <<Layer>> | 285 <<@macro layer>> > 286 > 287 When function is invoked, it first run in the @macro layer, and after that, > 288 it run in the neutral layer. Here is an example. > 289 > 290 >> @macro twice(x) { x; x } > 291 >> def f() { twice(print("Hello")); 999 } > 292 (function:173b6a0:1789720) > 293 >> f() > 294 Hello > 295 Hello > 296 999 > 297 > 298 When the interpreter evaluates f(), it first executes > 299 "twice(print("Hello")); 999" > 300 in the @macro layer. Basically what it does is to just construct its syntax t > 301 But, since we have defined the "twice" function in the @macro layer, it is > 302 execute as a function. Resulting syntax tree is > 303 "print("Hello"); print("Hello"); 999" > 304 and this is executed on the neutral (in this example, @value) layer. > 305 This is the reason why you see two "Hello"s. > 306 > 307 > 308 > 309 [[limitations]] > 310 > 311 This @macro layer is a very primitive one, and not a perfect macro language. > 312 Two major limitations are seen in the following "it" example. > 313 > 314 >> @macro LetItBe(x, y) { let it = x in y }; > 315 > 316 The variable name is not hygenic, and so without any effort, the syntax tree > 317 can access the outer variable "it". > 318 > 319 >> def foo() { LetItBe( 1+2+3, it*it ) } > 320 >> foo() > 321 36 > 322 > 323 Of course, this is not just a limitation; it can sometimes allow us to write > 324 many interesting macros. > 325 > 326 The other problem is that the macro expansion is only done at function startu > 327 So > 328 > 329 >> LetItBe( 1+2+3, it*it ) > 330 ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value > 331 > 332 you cannot directly use the macro in the same scope as the definition. > 333 You need to wrap it up in a function (like the foo() in the above example). > 334 > 335 > 336 > 337 [[quote and unquote]] > 338 > 339 Here is more involved example of code genration. > 340 From "x", it generates "x*x*x*x*x*x*x*x*x*x". > 341 > 342 @macro pow10(x) { > 343 @value( > 344 def pow(x, n) { > 345 if( n == 1 ) { x } > 346 else { > 347 @macro( @value(x) * @value(pow(x,n-1)) ) > 348 } > 349 } > 350 in > 351 pow(@macro(x),10) > 352 ) > 353 }; 133 354 134 to be written | 355 Here, x is a syntax tree but n is an actual integer. If you read carefully, > 356 you should get what is going on. Basically, @macro can be considered like > 357 quasiquoting and @value to be an escape from it.

Modified sample/macro.pmy from [a38c7267da8f14a3] to [274d10aca22ce25f].

7 def maxNormal(x,y) { 7 def maxNormal(x,y) { 8 if(x<y){y}else{x} 8 if(x<y){y}else{x} 9 }; 9 }; 10 @macro maxBad(x,y) { 10 @macro maxBad(x,y) { 11 if(x<y){y}else{x} 11 if(x<y){y}else{x} 12 }; 12 }; 13 13 14 @macro LetItBe(x, y) { | 14 @macro LetItBe(x, y) { let it = x in y }; 15 let it = x in y < 16 }; < 17 15 18 @macro pow10(x) { 16 @macro pow10(x) { 19 @v( | 17 @value( 20 def pow(x, n) { 18 def pow(x, n) { 21 if( n == 1 ) { x } 19 if( n == 1 ) { x } 22 else { 20 else { 23 @macro( @v(x) * @v(pow(x,n-1)) ) | 21 @macro( @value(x) * @value(pow(x,n-1)) ) 24 } 22 } 25 } 23 } 26 in 24 in 27 pow(@macro(x),10) 25 pow(@macro(x),10) 28 ) 26 ) 29 }; 27 }; 30 28