Index: index.dd ================================================================== --- index.dd +++ index.dd @@ -602,11 +602,11 @@ $(SECTION 外部とのやりとり, $(SECBODY $(TABLE $(TR $(TH print) $(TD (a)) $(TD a を文字列化標準出力に改行付きで表示)) $(TR $(TH argv) $(TD ) $(TD スクリプトに渡された引数文字列のconsリスト)) $(TR $(TH gensym) $(TD ()) $(TD エセgensym。変数名として他とかぶらなそうな文字列を返します)) - $(TR $(TH rand) $(TD (n)) $(TD 0 以上 n 未満の自然数をランダムに生成します)) + $(TR $(TH rand) $(TD (n)) $(TD 0 以上 n 未満の自然数を31bit以内でランダムに生成します)) ) ))
$(SECTION データ型判定, $(SECBODY Index: polemy/ast.d ================================================================== --- polemy/ast.d +++ polemy/ast.d @@ -13,10 +13,11 @@ abstract class AST { LexPosition pos; /// mixin SimpleConstructor; + invariant(){ assert(pos !is null);} } /// AST node for integer literal class Int : AST { Index: polemy/eval.d ================================================================== --- polemy/eval.d +++ polemy/eval.d @@ -413,10 +413,18 @@ @macro twice(x) { x; x }; def main() { twice(1) }; main() `) ); } +unittest +{ + auto e = new Evaluator; + enrollRuntimeLibrary(e); + assert_nothrow( e.evalString(`case 1`) ); + assert_nothrow( e.evalString(`case 1 when 1: 2`) ); +} + /* unittest { assert_eq( evalString(`var fac = fun(x){ if(x) Index: polemy/failure.d ================================================================== --- polemy/failure.d +++ polemy/failure.d @@ -21,11 +21,11 @@ mixin SimpleClass; override string toString() const { return sprintf!("%s:%d:%d")(filename, lineno, column); } static LexPosition dummy; - static this(){ dummy = new LexPosition("",0,0); } + static this(){ dummy = new LexPosition("",0,0); } } unittest { auto p = new LexPosition("hello.cpp", 123, 45); Index: polemy/parse.d ================================================================== --- polemy/parse.d +++ polemy/parse.d @@ -250,11 +250,11 @@ AST BaseExpression() { if( lex.empty ) throw genex!UnexpectedEOF(currentPosition(), "Reached EOF when tried to parse an expression"); - auto pos = lex.front.pos; + auto pos = currentPosition(); if( lex.front.quoted ) { scope(exit) lex.popFront; return new Str(pos, lex.front.str); } @@ -323,16 +323,16 @@ //==> // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFirst()) AST pmExpr = E(0); string pmVar = freshVarName(); string pmTryFirst = freshVarName(); - AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst, + AST pmBody = parsePatternMatchCases(pos, pmVar, pmTryFirst, new App(pos, new Var(pos, pmTryFirst))); return new Let(pos, pmVar, [], pmExpr, pmBody); } - AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST thenDoThis) + AST parsePatternMatchCases(LexPosition casePos, string pmVar, string tryThisBranchVar, AST thenDoThis) { // when pat: cBody //==> // ... let failBranchVar = ... in // let tryThisBranchVar = fun(){ if(test){cBody}else{failBranchVar()} } in thenDoThis @@ -345,21 +345,20 @@ eat(":", "after when pattern"); AST cBody = E(0); AST judgement = new App(pos, new Var(pos, "if"), ppTest(pmVar, pr), new Fun(pos,[],ppBind(pmVar, pr, cBody)), new Var(pos, failBranchVar)); - return parsePatternMatchCases(pmVar, failBranchVar, + return parsePatternMatchCases(casePos, pmVar, failBranchVar, new Let(pos, tryThisBranchVar, [], new Fun(pos,[],judgement), thenDoThis) ); } else { - auto pos = currentPosition(); - AST doNothing = new Fun(pos,[], - new Str(pos, sprintf!"(pattern match failure:%s)"(pos))); - return new Let(currentPosition(), tryThisBranchVar, [], doNothing, thenDoThis); + AST doNothing = new Fun(casePos,[], + new Str(casePos, sprintf!"(pattern match failure:%s)"(casePos))); + return new Let(casePos, tryThisBranchVar, [], doNothing, thenDoThis); } } // hageshiku tenuki abstract class SinglePattern @@ -557,11 +556,11 @@ return new Str(currentPosition(), "(empty function body)"); } LexPosition currentPosition() { - return lex.empty ? null : lex.front.pos; + return lex.empty ? new LexPosition("EOF",0,0) : lex.front.pos; } } unittest { Index: polemy/valueconv.d ================================================================== --- polemy/valueconv.d +++ polemy/valueconv.d @@ -20,11 +20,11 @@ auto ln = tt.access!IntValue(ValueLayer, "lineno"); auto cl = tt.access!IntValue(ValueLayer, "column"); if(fn !is null && ln !is null && cl !is null) return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); } - return null; + return LexPosition.dummy; } /// Experimental!! Convert Polemy value to D Value T polemy2d(T)(Value _v, LexPosition callpos=null) @@ -143,11 +143,20 @@ else static if(is(T : AST)) { assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) ); auto t = new Table; - t.set("pos", ValueLayer, ast2table(e.pos,rec)); + if(e.pos is null) // special treatment + { + Table post = new Table; + post.set("filename", ValueLayer, new StrValue("nullpo")); + post.set("lineno", ValueLayer, new IntValue(0)); + post.set("column", ValueLayer, new IntValue(0)); + t.set("pos", ValueLayer, post); + } + else + t.set("pos", ValueLayer, ast2table(e.pos,rec)); t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1])); foreach(i,m; e.tupleof) static if(is(typeof(m) : AST)) t.set(e.tupleof[i].stringof.split(".")[$-1], ValueLayer, rec(m)); else Index: sample/ast.pmy ================================================================== --- sample/ast.pmy +++ sample/ast.pmy @@ -9,10 +9,11 @@ var ev = @macro(e); case(ev) when {is:"App", fun:f, args:a}: ( ev {args: reverse(a, {})} +# {is:"App", fun:f, args:reverse(a, {})} ) when _ : ( ev )