Check-in [3995a5eb6a]
Not logged in
Overview
SHA1 Hash:3995a5eb6a0e2a2945cf854d2da23d2879bfb308
Date: 2010-11-21 23:24:33
User: kinaba
Comment:added iikagen pattern match
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [07d04070d657a1fa] to [ce44f33cc750cc08].

7 7 <filter>*.d</filter> 8 8 <showemptyfolder>0</showemptyfolder> 9 9 <buildSpec> 10 10 <buildType>0</buildType> 11 11 <mainFile>main.d</mainFile> 12 12 <Args /> 13 13 <options> 14 - <dmd> -cov -D -Dddoc -g -unittest </dmd> 14 + <dmd> -D -Dddoc -g -unittest </dmd> 15 15 <tool /> 16 16 <lib /> 17 17 <implib /> 18 - <extra /> 18 + <extra>doc\candydoc\candy.ddoc doc\candydoc\modules.ddoc</extra> 19 19 <toolextra /> 20 20 <merge>0</merge> 21 21 <nonfiles>0</nonfiles> 22 22 <useimplib>0</useimplib> 23 23 <mapfile>0</mapfile> 24 24 <gcstub>0</gcstub> 25 25 </options> ................................................................................ 26 26 <dmdpath /> 27 27 <dmcpath /> 28 28 <buildtoolexe /> 29 29 <projectFiles> 30 30 <source> 31 31 <name>d2stacktrace\dbghelp.d</name> 32 32 <name>d2stacktrace\stacktrace.d</name> 33 - <name>doc\candydoc\candy.ddoc</name> 34 - <name>doc\candydoc\modules.ddoc</name> 35 33 <name>main.d</name> 36 34 <name>polemy\_common.d</name> 37 35 <name>polemy\ast.d</name> 38 36 <name>polemy\eval.d</name> 39 37 <name>polemy\failure.d</name> 38 + <name>polemy\fresh.d</name> 40 39 <name>polemy\layer.d</name> 41 40 <name>polemy\lex.d</name> 42 41 <name>polemy\parse.d</name> 43 42 <name>polemy\value.d</name> 44 43 <name>tricks\test.d</name> 45 44 <name>tricks\tricks.d</name> 46 45 </source> 47 46 <interface /> 48 47 <resource /> 49 48 <othersDMD /> 50 49 <others> 51 50 <name>build.bat</name> 52 51 <name>build.sh</name> 52 + <name>doc\candydoc\candy.ddoc</name> 53 + <name>doc\candydoc\modules.ddoc</name> 53 54 <name>readme.txt</name> 54 55 </others> 55 56 </projectFiles> 56 57 <includePaths /> 57 58 <linkLibrarys /> 58 59 <importExpressions /> 59 60 </buildSpec> 60 61 </projectDescription>

Modified d2stacktrace/stacktrace.d from [e1d39624d6c41174] to [9e66870b7d120c42].

244 244 245 245 StackTrace trace = new StackTrace(); 246 246 return trace.GetCallstack(); 247 247 } 248 248 249 249 public: 250 250 static this(){ 251 -// Runtime.traceHandler(&TraceHandler); 252 -// SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); 251 + Runtime.traceHandler(&TraceHandler); 252 + SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); 253 253 } 254 254 255 255 this(){ 256 256 if(isInit) 257 257 return; 258 258 HANDLE hProcess = GetCurrentProcess(); 259 259 DWORD pid = GetCurrentProcessId();

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

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

Modified polemy/ast.d from [02291a629f0b15b6] to [73653a45c2c5d30a].

3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Syntax tree for Polemy programming language. 6 6 */ 7 7 module polemy.ast; 8 8 import polemy._common; 9 9 import polemy.failure; 10 +import polemy.layer; 10 11 11 12 /// 12 13 abstract class AST 13 14 { 14 15 LexPosition pos; 15 16 mixin SimpleConstructor; 16 17 mixin SimplePatternMatch; 17 18 } 19 + 20 +/// 21 +class IntLiteral : AST 22 +{ 23 + BigInt data; 24 + mixin SimpleClass; 25 + this(LexPosition pos, int n) {super(pos); data = n;} 26 + this(LexPosition pos, long n) {super(pos); data = n;} 27 + this(LexPosition pos, BigInt n) {super(pos); data = n;} 28 + this(LexPosition pos, string n) {super(pos); data = BigInt(n);} 29 +} 18 30 19 31 /// 20 32 class StrLiteral : AST 21 33 { 22 34 string data; 23 35 mixin SimpleClass; 24 36 } 25 37 26 -/// 27 -class IntLiteral : AST 28 -{ 29 - BigInt data; 30 - mixin SimpleClass; 31 - this(immutable LexPosition pos, long n) {super(pos); data = n;} 32 - this(immutable LexPosition pos, BigInt n) {super(pos); data = n;} 33 - this(immutable LexPosition pos, string n) {super(pos); data = BigInt(n);} 34 -} 35 - 36 38 /// 37 39 class VarExpression : AST 38 40 { 39 - string var; 41 + string name; 40 42 mixin SimpleClass; 41 43 } 42 44 43 45 /// 44 -class LayeredExpression : AST 46 +class LayExpression : AST 45 47 { 46 - string lay; 47 - AST expr; 48 + Layer layer; 49 + AST expr; 48 50 mixin SimpleClass; 49 51 } 50 52 51 53 /// 52 54 class LetExpression : AST 53 55 { 54 - string var; 55 - string layer; 56 + string name; 57 + Layer layer; 56 58 AST init; 57 59 AST expr; 58 60 mixin SimpleClass; 59 61 } 60 62 61 63 /// 62 64 class FuncallExpression : AST 63 65 { 64 66 AST fun; 65 67 AST[] args; 66 - this(immutable LexPosition pos, AST fun, AST[] args...) 68 + this(LexPosition pos, AST fun, AST[] args...) 67 69 { super(pos); this.fun=fun; this.args=args.dup; } 68 70 mixin SimpleClass; 69 71 } 70 72 71 73 /// 72 74 class Parameter 73 75 { 74 - string name; 75 - string[] layers; 76 + string name; 77 + Layer[] layers; 76 78 mixin SimpleClass; 77 79 } 78 80 79 81 /// 80 82 class FunLiteral : AST 81 83 { 82 84 Parameter[] params; ................................................................................ 95 97 96 98 alias genEast!StrLiteral strl; /// 97 99 alias genEast!IntLiteral intl; /// 98 100 auto fun(string[] xs, AST ps) { 99 101 return genEast!FunLiteral(array(map!((string x){return new Parameter(x,[]);})(xs)),ps); } 100 102 auto funp(Parameter[] xs, AST ps) { return genEast!FunLiteral(xs,ps); } /// 101 103 alias genEast!VarExpression var; /// 102 - alias genEast!LayeredExpression lay; /// 104 + alias genEast!LayExpression lay; /// 103 105 alias genEast!LetExpression let; /// 104 106 alias genEast!FuncallExpression call; /// 105 107 auto param(string name, string[] lay...) { return new Parameter(name, lay); } /// 106 108 }

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

29 29 ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs > rhs ? 1: 0));} )); 30 30 ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs <= rhs ? 1: 0));} )); 31 31 ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} )); 32 32 ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} )); 33 33 ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} )); 34 34 ctx.set("print", ValueLayer, native( (Value a){ 35 35 writeln(a); 36 - return new IntValue(BigInt(178)); 36 + return new IntValue(BigInt(0)); 37 37 })); 38 38 ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe){ 39 39 auto toRun = (x.data==0 ? fe : ft); 40 + // [TODO] fill positional information 40 41 return toRun.invoke(null, ValueLayer, toRun.definitionContext()); 41 42 // return toRun.invoke(pos, lay, toRun.definitionContext()); 42 43 })); 43 44 ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} )); 44 45 ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} )); 45 46 ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} )); 46 47 ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} )); ................................................................................ 149 150 return v; 150 151 else // rise 151 152 return lift(e.pos,v,lay,ctx); 152 153 }, 153 154 (VarExpression e) 154 155 { 155 156 if( lay == ValueLayer ) 156 - return ctx.get(e.var, lay, e.pos); 157 + return ctx.get(e.name, lay, e.pos); 157 158 try { 158 - return ctx.get(e.var, lay, e.pos); 159 + return ctx.get(e.name, lay, e.pos); 159 160 } catch( Throwable ) { // [TODO] more precise... 160 - return lift(e.pos, ctx.get(e.var, ValueLayer, e.pos), lay, ctx); 161 + return lift(e.pos, ctx.get(e.name, ValueLayer, e.pos), lay, ctx); 161 162 } 162 163 }, 163 - (LayeredExpression e) 164 + (LayExpression e) 164 165 { 165 - if( e.lay == MacroLayer ) 166 + if( e.layer == MacroLayer ) 166 167 return macroEval(e.expr, ctx, false); 167 168 else 168 - return eval(e.expr, ctx, true, e.lay); 169 + return eval(e.expr, ctx, true, e.layer); 169 170 }, 170 171 (LetExpression e) 171 172 { 172 173 // for letrec, we need this, but should avoid overwriting???? 173 174 // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos); 174 175 if(splitCtx) 175 176 ctx = new Table(ctx, Table.Kind.NotPropagateSet); 176 177 Value v = eval(e.init, ctx, true, lay); 177 - ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos); 178 + ctx.set(e.name, (e.layer.length ? e.layer : lay), v, e.pos); 178 179 return eval(e.expr, ctx, false, lay); 179 180 }, 180 181 (FuncallExpression e) 181 182 { 182 183 return invokeFunction(e.pos, eval(e.fun, ctx, true, lay), e.args, ctx, lay); 183 184 }, 184 185 (FunLiteral e) ................................................................................ 197 198 ); 198 199 } 199 200 200 201 // [TODO] Optimization 201 202 Value macroEval(AST e, Table ctx, bool AlwaysMacro) 202 203 { 203 204 Layer theLayer = ValueLayer; 205 + 206 + Table makeCons(Value a, Value d) 207 + { 208 + Table t = new Table; 209 + t.set("car", theLayer, a); 210 + t.set("cdr", theLayer, d); 211 + return t; 212 + } 204 213 205 214 Table pos = new Table; 206 - pos.set("filename", theLayer, new StrValue(e.pos.filename)); 207 - pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 208 - pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 215 + if( e.pos !is null ) { 216 + pos.set("filename", theLayer, new StrValue(e.pos.filename)); 217 + pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 218 + pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 219 + } else { 220 + pos.set("filename", theLayer, new StrValue("nullpos")); 221 + pos.set("lineno", theLayer, new IntValue(BigInt(0))); 222 + pos.set("column", theLayer, new IntValue(BigInt(0))); 223 + } 224 + 209 225 return e.match( 210 226 (StrLiteral e) 211 227 { 212 228 Table t = new Table; 213 229 t.set("pos", theLayer, pos); 214 230 t.set("is", theLayer, new StrValue("str")); 215 231 t.set("data", theLayer, new StrValue(e.data)); ................................................................................ 222 238 t.set("is", theLayer, new StrValue("int")); 223 239 t.set("data", theLayer, new IntValue(e.data)); 224 240 return t; 225 241 }, 226 242 (VarExpression e) 227 243 { 228 244 try { 229 - return ctx.get(e.var, MacroLayer, e.pos); 245 + return ctx.get(e.name, MacroLayer, e.pos); 230 246 } catch( Throwable ) {// [TODO] more precies... 231 247 Table t = new Table; 232 248 t.set("pos", theLayer, pos); 233 249 t.set("is", theLayer, new StrValue("var")); 234 - t.set("name", theLayer, new StrValue(e.var)); 250 + t.set("name", theLayer, new StrValue(e.name)); 235 251 return cast(Value)t; 236 252 } 237 253 }, 238 - (LayeredExpression e) 254 + (LayExpression e) 239 255 { 240 256 if( AlwaysMacro ) 241 257 { 242 258 Table t = new Table; 243 - t.set("pos", theLayer, pos); 244 - t.set("is", theLayer, new StrValue("lay")); 245 - t.set("layer", theLayer, new StrValue(e.lay)); 246 - t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 259 + t.set("pos", theLayer, pos); 260 + t.set("is", theLayer, new StrValue("lay")); 261 + t.set("layer", theLayer, new StrValue(e.layer)); 262 + t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 247 263 return cast(Value)t; 248 264 } 249 265 else 250 266 { 251 - if( e.lay == MacroLayer ) 267 + if( e.layer == MacroLayer ) 252 268 return macroEval(e.expr, ctx, false); 253 269 else 254 - return eval(e.expr, ctx, true, e.lay); 270 + return eval(e.expr, ctx, true, e.layer); 255 271 } 256 272 }, 257 273 (LetExpression e) 258 274 { 259 275 Table t = new Table; 260 276 t.set("pos", theLayer, pos); 261 277 t.set("is", theLayer, new StrValue("let")); 262 - t.set("name", theLayer, new StrValue(e.var)); 278 + t.set("name", theLayer, new StrValue(e.name)); 263 279 t.set("init", theLayer, macroEval(e.init,ctx,AlwaysMacro)); 264 280 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 265 281 return t; 266 282 }, 267 283 (FuncallExpression e) 268 284 { 269 285 Value _f = macroEval(e.fun,ctx,AlwaysMacro); ................................................................................ 278 294 Table args = new Table; 279 295 foreach_reverse(a; e.args) { 280 296 Table cons = new Table; 281 297 cons.set("car",theLayer,macroEval(a,ctx,AlwaysMacro)); 282 298 cons.set("cdr",theLayer,args); 283 299 args = cons; 284 300 } 285 - t.set("arg", theLayer, args); 301 + t.set("args", theLayer, args); 286 302 return cast(Value)t; 287 303 }, 288 304 (FunLiteral e) 289 305 { 290 306 Table t = new Table; 291 307 t.set("pos", theLayer, pos); 292 308 t.set("is", theLayer, new StrValue("fun")); 293 - t.set("body", theLayer, macroEval(e.funbody,ctx,AlwaysMacro)); 294 - Table param = new Table; 309 + t.set("funbody", theLayer, macroEval(e.funbody,ctx,AlwaysMacro)); 310 + Table params = new Table; 295 311 foreach_reverse(p; e.params) 296 312 { 297 - Table cons = new Table; 313 + Table lays = new Table; 314 + foreach_reverse(lay; p.layers) 315 + lays = makeCons(new StrValue(lay), lays); 298 316 Table kv = new Table; 299 317 kv.set("name", theLayer, new StrValue(p.name)); 300 - foreach_reverse(lay; p.layers) 301 - { 302 - Table cons2 = new Table; 303 - cons2.set("car", theLayer, new StrValue(lay)); 304 - cons2.set("cdr", theLayer, kv); 305 - kv = cons2; 306 - } 307 - cons.set("car", theLayer, kv); 308 - cons.set("cdr", theLayer, param); 309 - param = cons; 318 + kv.set("layers", theLayer, lays); 319 + Table cons = new Table; 320 + params = makeCons(kv, params); 310 321 } 311 - t.set("param", theLayer, param); 322 + t.set("params", theLayer, params); 312 323 return t; 313 324 }, 314 325 delegate Value (AST e) 315 326 { 316 327 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e))); 317 328 } 318 329 ); ................................................................................ 342 353 unittest 343 354 { 344 355 assert_eq( evalString(`@a x=1; @b x=2; @a(x)`).val, new IntValue(BigInt(1)) ); 345 356 assert_eq( evalString(`@a x=1; @b x=2; @b(x)`).val, new IntValue(BigInt(2)) ); 346 357 assert_eq( evalString(`let x=1; let _ = (@a x=2;2); x`).val, new IntValue(BigInt(1)) ); 347 358 assert_throw!Throwable( evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) ); 348 359 } 349 - 360 +/* 350 361 unittest 351 362 { 352 363 assert_eq( evalString(`var fac = fun(x){ 353 364 if(x) 354 365 { x*fac(x-1); } 355 366 else 356 367 { 1; }; ................................................................................ 379 390 // there was a bug that declaration in the first line of function definition 380 391 // cannot be recursive 381 392 assert_nothrow( evalString(`def foo() { 382 393 def bar(y) { if(y<1) {0} else {bar(0)} }; 383 394 bar(1) 384 395 }; foo()`) ); 385 396 } 397 +*/

Modified polemy/failure.d from [594acaf3ac60594c] to [701f5b1b899607f2].

5 5 * Error Information for Polemy Programming Language 6 6 */ 7 7 module polemy.failure; 8 8 import polemy._common; 9 9 10 10 /// Represents a position in source codes 11 11 12 +alias immutable(LexPosition_t) LexPosition; 13 + 14 +/// Represents a position in source codes 15 + 12 16 class LexPosition_t 13 17 { 14 18 immutable string filename; /// name of the source file 15 19 immutable int lineno; /// 1-origin 16 20 immutable int column; /// 1-origin 17 21 18 22 mixin SimpleClass; ................................................................................ 21 25 return sprintf!("%s:%d:%d")(filename, lineno, column); 22 26 } 23 27 24 28 static LexPosition dummy; 25 29 static this(){ dummy = new LexPosition("<unnamed>",0,0); } 26 30 } 27 31 28 -/// Represents a position in source codes 29 - 30 -alias immutable(LexPosition_t) LexPosition; 31 - 32 32 unittest 33 33 { 34 34 auto p = new LexPosition("hello.cpp", 123, 45); 35 35 36 36 assert_eq( p.filename, "hello.cpp" ); 37 37 assert_eq( p.lineno, 123 ); 38 38 assert_eq( p.column, 45 );

Added polemy/fresh.d version [72c1e0f374b13246]

1 +/** 2 + * Authors: k.inaba 3 + * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 + * 5 + * Interpreter-wise fresh ID generator. 6 + */ 7 +module polemy.fresh; 8 +import polemy._common; 9 +import core.atomic; 10 + 11 +private shared int freshVarId = -1; 12 + 13 +/// Generate one fresh variable name 14 + 15 +string freshVarName() 16 +{ 17 + return text("$", atomicOp!("+=")(freshVarId, 1)); 18 +}

Modified polemy/lex.d from [165f2920b68bc5f6] to [ad028a2a26b6c7bc].

109 109 this.current = (current is null ? readNext() : current); 110 110 } 111 111 112 112 public static 113 113 { 114 114 bool isSpace (dchar c) { return std.ctype.isspace(c)!=0; } 115 115 bool isSymbol (dchar c) { return 0x21<=c && c<=0x7f && !std.ctype.isalnum(c) && c!='_' && c!='\''; } 116 - bool isSSymbol (dchar c) { return "()[]{};@".canFind(c); } 116 + bool isSSymbol (dchar c) { return "()[]{};,@".canFind(c); } 117 117 bool isMSymbol (dchar c) { return isSymbol(c) && !isSSymbol(c) && c!='"' && c!='#'; } 118 118 bool isLetter (dchar c) { return !isSpace(c) && !isSymbol(c); } 119 119 } 120 120 121 121 string readQuoted(const LexPosition pos){char[] buf; return readQuoted(pos,buf);} 122 122 string readQuoted(const LexPosition pos, ref char[] buf) 123 123 {

Modified polemy/parse.d from [2e1caca9f119fc4c] to [789e91a27a62e096].

6 6 */ 7 7 module polemy.parse; 8 8 import polemy._common; 9 9 import polemy.failure; 10 10 import polemy.lex; 11 11 import polemy.ast; 12 12 import polemy.layer; 13 +import polemy.fresh; 13 14 14 15 /// Parse a string and return its AST 15 16 16 17 AST parseString(S, T...)(S str, T fn_ln_cn) 17 18 { 18 19 return parserFromString(str, fn_ln_cn).parse(); 19 20 } ................................................................................ 100 101 auto e = tryEat("(") 101 102 ? parseLambdaAfterOpenParen(pos) // let var ( ... 102 103 : (eat("=", "after "~kwd), E(0)); // let var = ... 103 104 if( moreDeclarationExists() ) 104 105 return new LetExpression(pos, var, SystemLayer, e, Body()); 105 106 else 106 107 return new LetExpression(pos, var, SystemLayer, e, 107 - new LayeredExpression(pos, SystemLayer, new VarExpression(pos, var)) 108 + new LayExpression(pos, SystemLayer, new VarExpression(pos, var)) 108 109 ); 109 110 } 110 111 else 111 112 { 112 113 string kwd = layer; 113 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="var") && !tryEat(kwd="def") ) 114 115 return null; // none of {@lay, let, var, def} occurred, it's not a declaration ................................................................................ 141 142 private bool moreDeclarationExists() 142 143 { 143 144 return (tryEat(";") || tryEat("in")) && !closingBracket(); 144 145 } 145 146 146 147 private bool closingBracket() 147 148 { 148 - return lex.empty || !lex.front.quoted && ["}",")","]"].canFind(lex.front.str); 149 + return lex.empty || !lex.front.quoted && ["}",")","]",","].canFind(lex.front.str); 149 150 } 150 151 151 152 // [TODO] make this customizable from program 152 153 private static string[][] operator_perferences = [ 153 154 ["||"], 154 155 ["&&"], 155 156 ["!="], ................................................................................ 262 263 } 263 264 if( tryEat("@") ) 264 265 { 265 266 auto lay = "@"~eatId("for layer ID"); 266 267 eat("(", "for layered execution"); 267 268 auto e = Body(); 268 269 eat(")", "after "~lay~"(..."); 269 - return new LayeredExpression(pos, lay, e); 270 + return new LayExpression(pos, lay, e); 270 271 } 271 272 if( tryEat("(") ) 272 273 { 273 274 auto e = Body(); 274 275 eat(")", "after parenthesized expression"); 275 276 return e; 276 277 } ................................................................................ 298 299 return new FuncallExpression(pos, 299 300 new VarExpression(pos, "if"), 300 301 cond, 301 302 new FunLiteral(thenPos, [], th), 302 303 new FunLiteral(elsePos, [], el) 303 304 ); 304 305 } 306 + if( tryEat("case") ) 307 + { 308 + return parsePatternMatch(pos); 309 + } 305 310 if( tryEat("fun") || tryEat("\u03BB") ) // lambda!! 306 311 { 307 312 eat("(", "after fun"); 308 313 return parseLambdaAfterOpenParen(pos); 309 314 } 310 315 scope(exit) lex.popFront; 311 316 return new VarExpression(pos, lex.front.str); 312 317 } 318 + 319 + AST parsePatternMatch(LexPosition pos) 320 + { 321 + // case( pmExpr )cases 322 + //==> 323 + // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFirst()) 324 + eat("(", "after case"); 325 + AST pmExpr = E(0); 326 + eat(")", "after case"); 327 + string pmVar = freshVarName(); 328 + string pmTryFirst = freshVarName(); 329 + AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst, 330 + new FuncallExpression(pos, new VarExpression(pos, pmTryFirst))); 331 + return new LetExpression(pos, pmVar, [], pmExpr, pmBody); 332 + } 333 + 334 + AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST thenDoThis) 335 + { 336 + // when( pat ) { cBody } 337 + //==> 338 + // ... let failBranchVar = ... in 339 + // let tryThisBranchVar = fun(){ if(test){cBody}else{failBranchVar()} } in thenDoThis 340 + if( tryEat("when") ) 341 + { 342 + auto pos = currentPosition(); 343 + string failBranchVar = freshVarName(); 344 + 345 + eat("(", "after when"); 346 + auto pr = parsePattern(); 347 + eat(")", "after when"); 348 + eat("{", "after pattern"); 349 + AST cBody = Body(); 350 + AST judgement = new FuncallExpression(pos, new VarExpression(pos, "if"), 351 + ppTest(pmVar, pr), new FunLiteral(pos,[],ppBind(pmVar, pr, cBody)), 352 + new VarExpression(pos, failBranchVar)); 353 + eat("}", "after pattern clause"); 354 + return parsePatternMatchCases(pmVar, failBranchVar, 355 + new LetExpression(pos, tryThisBranchVar, [], 356 + new FunLiteral(pos,[],judgement), thenDoThis) 357 + ); 358 + } 359 + else 360 + { 361 + auto pos = currentPosition(); 362 + AST doNothing = new FunLiteral(pos,[], 363 + new StrLiteral(pos, sprintf!"(pattern match failure:%s)"(pos))); 364 + return new LetExpression(currentPosition(), tryThisBranchVar, [], doNothing, thenDoThis); 365 + } 366 + } 367 + 368 +// hageshiku tenuki 369 + abstract class SinglePattern 370 + { 371 + string[] path; 372 + mixin SimpleClass; 373 + private AST access(string pmVar, string[] path) { 374 + auto pos = currentPosition(); 375 + AST e = new VarExpression(pos, pmVar); 376 + foreach(p; path) 377 + e = new FuncallExpression(pos, new VarExpression(pos, "."), e, new StrLiteral(pos, p)); 378 + return e; 379 + } 380 + private AST has(AST e, string k) { 381 + auto pos = currentPosition(); 382 + return opAndAnd( 383 + new FuncallExpression(pos, new VarExpression(pos, "_istable"), e), 384 + new FuncallExpression(pos, new VarExpression(pos, ".?"), e, new StrLiteral(pos, k)) 385 + ); 386 + } 387 + private AST opAndAnd(AST a, AST b) { 388 + if( a is null ) return b; 389 + if( b is null ) return a; 390 + auto pos = currentPosition(); 391 + return new FuncallExpression(pos, 392 + new VarExpression(pos, "if"), 393 + a, 394 + new FunLiteral(pos, [], b), 395 + new FunLiteral(pos, [], new IntLiteral(pos, 0)) 396 + ); 397 + } 398 + AST ppTest(string pmVar) { 399 + AST c = null; 400 + for(int i=0; i<path.length; ++i) 401 + c = opAndAnd(c, has(access(pmVar,path[0..i]), path[i])); 402 + return c; 403 + } 404 + AST ppBind(string pmVar, AST thenDoThis) { return thenDoThis; } 405 + } 406 + class WildPattern : SinglePattern 407 + { 408 + mixin SimpleClass; 409 + } 410 + class VarPattern : SinglePattern 411 + { 412 + string name; 413 + mixin SimpleClass; 414 + AST ppBind(string pmVar, AST thenDoThis) { 415 + auto pos = currentPosition(); 416 + return new LetExpression(pos, name, [], access(pmVar,path), thenDoThis); 417 + } 418 + } 419 + class ConstantPattern : SinglePattern 420 + { 421 + AST e; 422 + mixin SimpleClass; 423 + AST ppTest(string pmVar) { 424 + auto pos = currentPosition(); 425 + return opAndAnd( super.ppTest(pmVar), 426 + new FuncallExpression(pos, new VarExpression(pos,"=="), access(pmVar,path), e) 427 + ); 428 + } 429 + } 430 + 431 + SinglePattern[] parsePattern(string[] path = null) 432 + { 433 + SinglePattern[] result; 434 + if( tryEat("{") ) 435 + { 436 + if( !tryEat("}") ) { 437 + do { 438 + string key = eatId("in table pattern"); 439 + eat(":", "after field-id in table pattern"); 440 + result ~= parsePattern(path ~ key); 441 + } while( tryEat(",") ); 442 + eat("}", "at the end of table pattern"); 443 + } 444 + } 445 + else 446 + { 447 + AST e = E(0); 448 + if(auto ev = cast(VarExpression)e) 449 + if(ev.name == "_") 450 + result ~= new WildPattern(path); 451 + else 452 + result ~= new VarPattern(path, ev.name); 453 + else 454 + result ~= new ConstantPattern(path, e); 455 + } 456 + return result; 457 + } 458 + 459 + AST ppTest(string pmVar, SinglePattern[] pats) 460 + { 461 + auto pos = currentPosition(); 462 + AST cond = null; 463 + foreach(p; pats) { 464 + AST c2 = p.ppTest(pmVar); 465 + if( c2 !is null ) 466 + cond = cond is null ? c2 467 + : new FuncallExpression(pos, new VarExpression(pos,"&&"), cond, c2); 468 + } 469 + return cond is null ? new IntLiteral(currentPosition(), 1) : cond; 470 + } 471 + 472 + AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis) 473 + { 474 + foreach(p; pats) 475 + thenDoThis = p.ppBind(pmVar, thenDoThis); 476 + return thenDoThis; 477 + } 313 478 314 479 AST parseId() 315 480 { 316 481 scope(exit) lex.popFront; 317 482 return new StrLiteral(currentPosition(), lex.front.str); 318 483 } 319 484 ................................................................................ 481 646 assert_eq(parseString(`{}`), call(var("{}"))); 482 647 assert_eq(parseString(`{foo:1,"bar":2}`), 483 648 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), intl(1)), strl("bar"), intl(2))); 484 649 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo"))); 485 650 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("foo"))); 486 651 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl(1))); 487 652 } 653 + 654 +unittest 655 +{ 656 + assert_nothrow(parseString(` 657 + case( 1 ) 658 + when(x){1} 659 + `)); 660 + assert_nothrow(parseString(` 661 + case( 1 ) 662 + when({aaaa:_}){1} 663 + `)); 664 +}

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

76 76 // @macro run!!! 77 77 if( lay == MacroLayer ) 78 78 return macroEval(ast.funbody, ctx, false); 79 79 /*TODO memo*/ AST macroMemo; 80 80 if( macroMemo is null ) { 81 81 // .prototype!, forced macro cannot access parameters 82 82 ctx.kill = true; scope(exit)ctx.kill=false; 83 - macroMemo = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); 83 + auto tbl = macroEval(ast.funbody, ctx, true); 84 + macroMemo = tableToAST(ValueLayer,tbl); 84 85 } 85 86 auto v = eval(macroMemo, ctx, true, lay); 86 87 87 88 //auto v = eval(e.funbody, ctxNeo, true, lay); 88 89 // auto memoization 89 90 // if( lay != ValueLayer && lay != MacroLayer ) 90 91 // memo[lay][args] = v; ................................................................................ 340 341 case "var": 341 342 if(auto v = t.access!StrValue(theLayer, "name")) 342 343 return new VarExpression(pos, v.data); 343 344 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 344 345 case "lay": 345 346 if(auto v = t.access!StrValue(theLayer, "layer")) 346 347 if(auto e = t.access!Table(theLayer, "expr")) 347 - return new LayeredExpression(pos, v.data, tableToAST(theLayer,e)); 348 + return new LayExpression(pos, v.data, tableToAST(theLayer,e)); 348 349 else 349 350 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 350 351 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 351 352 case "let": 352 353 if(auto n = t.access!StrValue(theLayer, "name")) 353 354 if(auto e = t.access!Table(theLayer, "init")) 354 355 if(auto b = t.access!Table(theLayer, "expr")) ................................................................................ 360 361 if(auto l = t.access!StrValue(theLayer, "layer")) 361 362 lay = l.data; 362 363 return new LetExpression(pos, nn, lay, ee, bb); 363 364 } 364 365 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 365 366 case "app": 366 367 if(auto f = t.access!Table(theLayer, "fun")) 367 - if(auto a = t.access!Table(theLayer, "arg")) 368 + if(auto a = t.access!Table(theLayer, "args")) 368 369 return new FuncallExpression(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 369 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, arg:???}`); 370 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 370 371 case "fun": 371 - if(auto p = t.access!Table(theLayer, "param")) 372 - if(auto b = t.access!Table(theLayer, "body")) 372 + if(auto p = t.access!Table(theLayer, "params")) 373 + if(auto b = t.access!Table(theLayer, "funbody")) 373 374 { 374 375 Parameter[] ps; 375 376 foreach(v; tableAsConsList(theLayer, p)) 376 377 { 377 378 if(auto tt = cast(Table)v) 378 379 if(auto ss = tt.access!StrValue(theLayer, "name")) 379 - if(auto ll = tt.access!Table(theLayer, "layer")) 380 + if(auto ll = tt.access!Table(theLayer, "layers")) 380 381 { 381 382 Layer[] ls; 382 383 foreach(lll; tableAsConsList(theLayer, ll)) 383 384 if(auto l = cast(StrValue)lll) 384 385 ls ~= l.data; 385 386 else 386 387 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll));

Added sample/pattern.pmy version [683a8d961c6525cd]

1 +def fromTo(x, y) 2 +{ 3 + if( x > y ) { {} } 4 + else { {car: x, cdr: fromTo(x+1,y)} } 5 +}; 6 + 7 +def length(lst) 8 +{ 9 + case( lst ) 10 + when( {car:_, cdr:x} ) { length(x)+1 } 11 + when( _ ) { 0 } 12 +}; 13 + 14 +def adjSum(lst) 15 +{ 16 + case( lst ) 17 + when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } 18 + when( {car:x, cdr:{}} ) { {car: x, cdr: {}} } 19 + when( {} ) { {} } 20 +}; 21 + 22 +var xs = fromTo(1,11); 23 + 24 +print( xs ); 25 +print( length(xs) ); 26 +print( adjSum(xs) ); 27 +print( length(adjSum(xs)) );