Index: .poseidon
==================================================================
--- .poseidon
+++ .poseidon
@@ -9,15 +9,15 @@
0
main.d
- -cov -D -Dddoc -g -unittest
+ -D -Dddoc -g -unittest
-
+ doc\candydoc\candy.ddoc doc\candydoc\modules.ddoc
0
0
0
0
@@ -28,17 +28,16 @@
Index: d2stacktrace/stacktrace.d
==================================================================
--- d2stacktrace/stacktrace.d
+++ d2stacktrace/stacktrace.d
@@ -246,12 +246,12 @@
return trace.GetCallstack();
}
public:
static this(){
-// Runtime.traceHandler(&TraceHandler);
-// SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler);
+ Runtime.traceHandler(&TraceHandler);
+ SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler);
}
this(){
if(isInit)
return;
Index: doc/candydoc/modules.ddoc
==================================================================
--- doc/candydoc/modules.ddoc
+++ doc/candydoc/modules.ddoc
@@ -3,10 +3,11 @@
$(MODULE tricks.tricks)
$(MODULE tricks.test)
$(MODULE polemy._common)
$(MODULE polemy.failure)
$(MODULE polemy.layer)
+ $(MODULE polemy.fresh)
$(MODULE polemy.lex)
$(MODULE polemy.parse)
$(MODULE polemy.ast)
$(MODULE polemy.eval)
$(MODULE polemy.value)
Index: polemy/ast.d
==================================================================
--- polemy/ast.d
+++ polemy/ast.d
@@ -5,56 +5,58 @@
* Syntax tree for Polemy programming language.
*/
module polemy.ast;
import polemy._common;
import polemy.failure;
+import polemy.layer;
///
abstract class AST
{
LexPosition pos;
mixin SimpleConstructor;
mixin SimplePatternMatch;
}
+///
+class IntLiteral : AST
+{
+ BigInt data;
+ mixin SimpleClass;
+ this(LexPosition pos, int n) {super(pos); data = n;}
+ this(LexPosition pos, long n) {super(pos); data = n;}
+ this(LexPosition pos, BigInt n) {super(pos); data = n;}
+ this(LexPosition pos, string n) {super(pos); data = BigInt(n);}
+}
+
///
class StrLiteral : AST
{
string data;
mixin SimpleClass;
}
-///
-class IntLiteral : AST
-{
- BigInt data;
- mixin SimpleClass;
- this(immutable LexPosition pos, long n) {super(pos); data = n;}
- this(immutable LexPosition pos, BigInt n) {super(pos); data = n;}
- this(immutable LexPosition pos, string n) {super(pos); data = BigInt(n);}
-}
-
///
class VarExpression : AST
{
- string var;
+ string name;
mixin SimpleClass;
}
///
-class LayeredExpression : AST
+class LayExpression : AST
{
- string lay;
- AST expr;
+ Layer layer;
+ AST expr;
mixin SimpleClass;
}
///
class LetExpression : AST
{
- string var;
- string layer;
+ string name;
+ Layer layer;
AST init;
AST expr;
mixin SimpleClass;
}
@@ -61,20 +63,20 @@
///
class FuncallExpression : AST
{
AST fun;
AST[] args;
- this(immutable LexPosition pos, AST fun, AST[] args...)
+ this(LexPosition pos, AST fun, AST[] args...)
{ super(pos); this.fun=fun; this.args=args.dup; }
mixin SimpleClass;
}
///
class Parameter
{
- string name;
- string[] layers;
+ string name;
+ Layer[] layers;
mixin SimpleClass;
}
///
class FunLiteral : AST
@@ -97,10 +99,10 @@
alias genEast!IntLiteral intl; ///
auto fun(string[] xs, AST ps) {
return genEast!FunLiteral(array(map!((string x){return new Parameter(x,[]);})(xs)),ps); }
auto funp(Parameter[] xs, AST ps) { return genEast!FunLiteral(xs,ps); } ///
alias genEast!VarExpression var; ///
- alias genEast!LayeredExpression lay; ///
+ alias genEast!LayExpression lay; ///
alias genEast!LetExpression let; ///
alias genEast!FuncallExpression call; ///
auto param(string name, string[] lay...) { return new Parameter(name, lay); } ///
}
Index: polemy/eval.d
==================================================================
--- polemy/eval.d
+++ polemy/eval.d
@@ -31,14 +31,15 @@
ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} ));
ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} ));
ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} ));
ctx.set("print", ValueLayer, native( (Value a){
writeln(a);
- return new IntValue(BigInt(178));
+ return new IntValue(BigInt(0));
}));
ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe){
auto toRun = (x.data==0 ? fe : ft);
+ // [TODO] fill positional information
return toRun.invoke(null, ValueLayer, toRun.definitionContext());
// return toRun.invoke(pos, lay, toRun.definitionContext());
}));
ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} ));
ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} ));
@@ -151,32 +152,32 @@
return lift(e.pos,v,lay,ctx);
},
(VarExpression e)
{
if( lay == ValueLayer )
- return ctx.get(e.var, lay, e.pos);
+ return ctx.get(e.name, lay, e.pos);
try {
- return ctx.get(e.var, lay, e.pos);
+ return ctx.get(e.name, lay, e.pos);
} catch( Throwable ) { // [TODO] more precise...
- return lift(e.pos, ctx.get(e.var, ValueLayer, e.pos), lay, ctx);
+ return lift(e.pos, ctx.get(e.name, ValueLayer, e.pos), lay, ctx);
}
},
- (LayeredExpression e)
+ (LayExpression e)
{
- if( e.lay == MacroLayer )
+ if( e.layer == MacroLayer )
return macroEval(e.expr, ctx, false);
else
- return eval(e.expr, ctx, true, e.lay);
+ return eval(e.expr, ctx, true, e.layer);
},
(LetExpression e)
{
// for letrec, we need this, but should avoid overwriting????
// ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos);
if(splitCtx)
ctx = new Table(ctx, Table.Kind.NotPropagateSet);
Value v = eval(e.init, ctx, true, lay);
- ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos);
+ ctx.set(e.name, (e.layer.length ? e.layer : lay), v, e.pos);
return eval(e.expr, ctx, false, lay);
},
(FuncallExpression e)
{
return invokeFunction(e.pos, eval(e.fun, ctx, true, lay), e.args, ctx, lay);
@@ -193,21 +194,36 @@
delegate Value (AST e)
{
throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e)));
}
);
-}
+}
// [TODO] Optimization
Value macroEval(AST e, Table ctx, bool AlwaysMacro)
{
Layer theLayer = ValueLayer;
+
+ Table makeCons(Value a, Value d)
+ {
+ Table t = new Table;
+ t.set("car", theLayer, a);
+ t.set("cdr", theLayer, d);
+ return t;
+ }
Table pos = new Table;
- pos.set("filename", theLayer, new StrValue(e.pos.filename));
- pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno)));
- pos.set("column", theLayer, new IntValue(BigInt(e.pos.column)));
+ if( e.pos !is null ) {
+ pos.set("filename", theLayer, new StrValue(e.pos.filename));
+ pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno)));
+ pos.set("column", theLayer, new IntValue(BigInt(e.pos.column)));
+ } else {
+ pos.set("filename", theLayer, new StrValue("nullpos"));
+ pos.set("lineno", theLayer, new IntValue(BigInt(0)));
+ pos.set("column", theLayer, new IntValue(BigInt(0)));
+ }
+
return e.match(
(StrLiteral e)
{
Table t = new Table;
t.set("pos", theLayer, pos);
@@ -224,44 +240,44 @@
return t;
},
(VarExpression e)
{
try {
- return ctx.get(e.var, MacroLayer, e.pos);
+ return ctx.get(e.name, MacroLayer, e.pos);
} catch( Throwable ) {// [TODO] more precies...
Table t = new Table;
t.set("pos", theLayer, pos);
t.set("is", theLayer, new StrValue("var"));
- t.set("name", theLayer, new StrValue(e.var));
+ t.set("name", theLayer, new StrValue(e.name));
return cast(Value)t;
}
},
- (LayeredExpression e)
+ (LayExpression e)
{
if( AlwaysMacro )
{
Table t = new Table;
- t.set("pos", theLayer, pos);
- t.set("is", theLayer, new StrValue("lay"));
- t.set("layer", theLayer, new StrValue(e.lay));
- t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro));
+ t.set("pos", theLayer, pos);
+ t.set("is", theLayer, new StrValue("lay"));
+ t.set("layer", theLayer, new StrValue(e.layer));
+ t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro));
return cast(Value)t;
}
else
{
- if( e.lay == MacroLayer )
+ if( e.layer == MacroLayer )
return macroEval(e.expr, ctx, false);
else
- return eval(e.expr, ctx, true, e.lay);
+ return eval(e.expr, ctx, true, e.layer);
}
},
(LetExpression e)
{
Table t = new Table;
t.set("pos", theLayer, pos);
t.set("is", theLayer, new StrValue("let"));
- t.set("name", theLayer, new StrValue(e.var));
+ t.set("name", theLayer, new StrValue(e.name));
t.set("init", theLayer, macroEval(e.init,ctx,AlwaysMacro));
t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro));
return t;
},
(FuncallExpression e)
@@ -280,37 +296,32 @@
Table cons = new Table;
cons.set("car",theLayer,macroEval(a,ctx,AlwaysMacro));
cons.set("cdr",theLayer,args);
args = cons;
}
- t.set("arg", theLayer, args);
+ t.set("args", theLayer, args);
return cast(Value)t;
},
(FunLiteral e)
{
Table t = new Table;
t.set("pos", theLayer, pos);
t.set("is", theLayer, new StrValue("fun"));
- t.set("body", theLayer, macroEval(e.funbody,ctx,AlwaysMacro));
- Table param = new Table;
+ t.set("funbody", theLayer, macroEval(e.funbody,ctx,AlwaysMacro));
+ Table params = new Table;
foreach_reverse(p; e.params)
{
- Table cons = new Table;
+ Table lays = new Table;
+ foreach_reverse(lay; p.layers)
+ lays = makeCons(new StrValue(lay), lays);
Table kv = new Table;
kv.set("name", theLayer, new StrValue(p.name));
- foreach_reverse(lay; p.layers)
- {
- Table cons2 = new Table;
- cons2.set("car", theLayer, new StrValue(lay));
- cons2.set("cdr", theLayer, kv);
- kv = cons2;
- }
- cons.set("car", theLayer, kv);
- cons.set("cdr", theLayer, param);
- param = cons;
+ kv.set("layers", theLayer, lays);
+ Table cons = new Table;
+ params = makeCons(kv, params);
}
- t.set("param", theLayer, param);
+ t.set("params", theLayer, params);
return t;
},
delegate Value (AST e)
{
throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e)));
@@ -344,11 +355,11 @@
assert_eq( evalString(`@a x=1; @b x=2; @a(x)`).val, new IntValue(BigInt(1)) );
assert_eq( evalString(`@a x=1; @b x=2; @b(x)`).val, new IntValue(BigInt(2)) );
assert_eq( evalString(`let x=1; let _ = (@a x=2;2); x`).val, new IntValue(BigInt(1)) );
assert_throw!Throwable( evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) );
}
-
+/*
unittest
{
assert_eq( evalString(`var fac = fun(x){
if(x)
{ x*fac(x-1); }
@@ -381,5 +392,6 @@
assert_nothrow( evalString(`def foo() {
def bar(y) { if(y<1) {0} else {bar(0)} };
bar(1)
}; foo()`) );
}
+*/
Index: polemy/failure.d
==================================================================
--- polemy/failure.d
+++ polemy/failure.d
@@ -7,10 +7,14 @@
module polemy.failure;
import polemy._common;
/// Represents a position in source codes
+alias immutable(LexPosition_t) LexPosition;
+
+/// Represents a position in source codes
+
class LexPosition_t
{
immutable string filename; /// name of the source file
immutable int lineno; /// 1-origin
immutable int column; /// 1-origin
@@ -23,14 +27,10 @@
static LexPosition dummy;
static this(){ dummy = new LexPosition("",0,0); }
}
-/// Represents a position in source codes
-
-alias immutable(LexPosition_t) LexPosition;
-
unittest
{
auto p = new LexPosition("hello.cpp", 123, 45);
assert_eq( p.filename, "hello.cpp" );
ADDED polemy/fresh.d
Index: polemy/fresh.d
==================================================================
--- polemy/fresh.d
+++ polemy/fresh.d
@@ -0,0 +1,18 @@
+/**
+ * Authors: k.inaba
+ * License: NYSL 0.9982 http://www.kmonos.net/nysl/
+ *
+ * Interpreter-wise fresh ID generator.
+ */
+module polemy.fresh;
+import polemy._common;
+import core.atomic;
+
+private shared int freshVarId = -1;
+
+/// Generate one fresh variable name
+
+string freshVarName()
+{
+ return text("$", atomicOp!("+=")(freshVarId, 1));
+}
Index: polemy/lex.d
==================================================================
--- polemy/lex.d
+++ polemy/lex.d
@@ -111,11 +111,11 @@
public static
{
bool isSpace (dchar c) { return std.ctype.isspace(c)!=0; }
bool isSymbol (dchar c) { return 0x21<=c && c<=0x7f && !std.ctype.isalnum(c) && c!='_' && c!='\''; }
- bool isSSymbol (dchar c) { return "()[]{};@".canFind(c); }
+ bool isSSymbol (dchar c) { return "()[]{};,@".canFind(c); }
bool isMSymbol (dchar c) { return isSymbol(c) && !isSSymbol(c) && c!='"' && c!='#'; }
bool isLetter (dchar c) { return !isSpace(c) && !isSymbol(c); }
}
string readQuoted(const LexPosition pos){char[] buf; return readQuoted(pos,buf);}
Index: polemy/parse.d
==================================================================
--- polemy/parse.d
+++ polemy/parse.d
@@ -7,11 +7,12 @@
module polemy.parse;
import polemy._common;
import polemy.failure;
import polemy.lex;
import polemy.ast;
-import polemy.layer;
+import polemy.layer;
+import polemy.fresh;
/// Parse a string and return its AST
AST parseString(S, T...)(S str, T fn_ln_cn)
{
@@ -102,11 +103,11 @@
: (eat("=", "after "~kwd), E(0)); // let var = ...
if( moreDeclarationExists() )
return new LetExpression(pos, var, SystemLayer, e, Body());
else
return new LetExpression(pos, var, SystemLayer, e,
- new LayeredExpression(pos, SystemLayer, new VarExpression(pos, var))
+ new LayExpression(pos, SystemLayer, new VarExpression(pos, var))
);
}
else
{
string kwd = layer;
@@ -143,11 +144,11 @@
return (tryEat(";") || tryEat("in")) && !closingBracket();
}
private bool closingBracket()
{
- return lex.empty || !lex.front.quoted && ["}",")","]"].canFind(lex.front.str);
+ return lex.empty || !lex.front.quoted && ["}",")","]",","].canFind(lex.front.str);
}
// [TODO] make this customizable from program
private static string[][] operator_perferences = [
["||"],
@@ -264,11 +265,11 @@
{
auto lay = "@"~eatId("for layer ID");
eat("(", "for layered execution");
auto e = Body();
eat(")", "after "~lay~"(...");
- return new LayeredExpression(pos, lay, e);
+ return new LayExpression(pos, lay, e);
}
if( tryEat("(") )
{
auto e = Body();
eat(")", "after parenthesized expression");
@@ -300,18 +301,182 @@
cond,
new FunLiteral(thenPos, [], th),
new FunLiteral(elsePos, [], el)
);
}
+ if( tryEat("case") )
+ {
+ return parsePatternMatch(pos);
+ }
if( tryEat("fun") || tryEat("\u03BB") ) // lambda!!
{
eat("(", "after fun");
return parseLambdaAfterOpenParen(pos);
}
scope(exit) lex.popFront;
return new VarExpression(pos, lex.front.str);
}
+
+ AST parsePatternMatch(LexPosition pos)
+ {
+ // case( pmExpr )cases
+ //==>
+ // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFirst())
+ eat("(", "after case");
+ AST pmExpr = E(0);
+ eat(")", "after case");
+ string pmVar = freshVarName();
+ string pmTryFirst = freshVarName();
+ AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst,
+ new FuncallExpression(pos, new VarExpression(pos, pmTryFirst)));
+ return new LetExpression(pos, pmVar, [], pmExpr, pmBody);
+ }
+
+ AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST thenDoThis)
+ {
+ // when( pat ) { cBody }
+ //==>
+ // ... let failBranchVar = ... in
+ // let tryThisBranchVar = fun(){ if(test){cBody}else{failBranchVar()} } in thenDoThis
+ if( tryEat("when") )
+ {
+ auto pos = currentPosition();
+ string failBranchVar = freshVarName();
+
+ eat("(", "after when");
+ auto pr = parsePattern();
+ eat(")", "after when");
+ eat("{", "after pattern");
+ AST cBody = Body();
+ AST judgement = new FuncallExpression(pos, new VarExpression(pos, "if"),
+ ppTest(pmVar, pr), new FunLiteral(pos,[],ppBind(pmVar, pr, cBody)),
+ new VarExpression(pos, failBranchVar));
+ eat("}", "after pattern clause");
+ return parsePatternMatchCases(pmVar, failBranchVar,
+ new LetExpression(pos, tryThisBranchVar, [],
+ new FunLiteral(pos,[],judgement), thenDoThis)
+ );
+ }
+ else
+ {
+ auto pos = currentPosition();
+ AST doNothing = new FunLiteral(pos,[],
+ new StrLiteral(pos, sprintf!"(pattern match failure:%s)"(pos)));
+ return new LetExpression(currentPosition(), tryThisBranchVar, [], doNothing, thenDoThis);
+ }
+ }
+
+// hageshiku tenuki
+ abstract class SinglePattern
+ {
+ string[] path;
+ mixin SimpleClass;
+ private AST access(string pmVar, string[] path) {
+ auto pos = currentPosition();
+ AST e = new VarExpression(pos, pmVar);
+ foreach(p; path)
+ e = new FuncallExpression(pos, new VarExpression(pos, "."), e, new StrLiteral(pos, p));
+ return e;
+ }
+ private AST has(AST e, string k) {
+ auto pos = currentPosition();
+ return opAndAnd(
+ new FuncallExpression(pos, new VarExpression(pos, "_istable"), e),
+ new FuncallExpression(pos, new VarExpression(pos, ".?"), e, new StrLiteral(pos, k))
+ );
+ }
+ private AST opAndAnd(AST a, AST b) {
+ if( a is null ) return b;
+ if( b is null ) return a;
+ auto pos = currentPosition();
+ return new FuncallExpression(pos,
+ new VarExpression(pos, "if"),
+ a,
+ new FunLiteral(pos, [], b),
+ new FunLiteral(pos, [], new IntLiteral(pos, 0))
+ );
+ }
+ AST ppTest(string pmVar) {
+ AST c = null;
+ for(int i=0; i y ) { {} }
+ else { {car: x, cdr: fromTo(x+1,y)} }
+};
+
+def length(lst)
+{
+ case( lst )
+ when( {car:_, cdr:x} ) { length(x)+1 }
+ when( _ ) { 0 }
+};
+
+def adjSum(lst)
+{
+ case( lst )
+ when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} }
+ when( {car:x, cdr:{}} ) { {car: x, cdr: {}} }
+ when( {} ) { {} }
+};
+
+var xs = fromTo(1,11);
+
+print( xs );
+print( length(xs) );
+print( adjSum(xs) );
+print( length(adjSum(xs)) );