Check-in [aa770610d3]
Not logged in
Overview
SHA1 Hash:aa770610d34f6f4d77cad5d3fb52a6193055993f
Date: 2010-11-09 01:40:55
User: kinaba
Comment:added layered-let
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [1c3854b81b30b626] to [2bab91be5bee6d2e].

32 32 <name>d2stacktrace\stacktrace.d</name> 33 33 <name>main.d</name> 34 34 <name>polemy\_common.d</name> 35 35 <name>polemy\ast.d</name> 36 36 <name>polemy\lex.d</name> 37 37 <name>polemy\parse.d</name> 38 38 <name>polemy\tricks.d</name> 39 + <name>polemy\value.d</name> 39 40 </source> 40 41 <interface /> 41 42 <resource /> 42 43 <othersDMD /> 43 44 <others> 44 45 <name>build.bat</name> 45 46 <name>build.sh</name>

Modified main.d from [e7185e89f4df4ae3] to [404b54e69646e17a].

5 5 * Entry point for Polemy interpreter. 6 6 */ 7 7 8 8 import std.stdio; 9 9 10 10 version(unittest) static ~this() 11 11 { 12 - writeln( "***********************" ); 13 - writeln( "* All Tests Passed <3 *" ); 14 - writeln( "*********************** (Press Enter to finish)" ); 12 + writeln( "(Press Enter to finish)" ); 15 13 readln(); 16 14 } 17 15 18 16 void main( string[] args ) 19 17 { 20 18 }

Modified polemy/ast.d from [4e37845b6ce5021a] to [35d37c6aa0a6531e].

34 34 string var; 35 35 mixin SimpleClass; 36 36 } 37 37 38 38 class LetExpression : AST 39 39 { 40 40 string var; 41 + string layer; 41 42 AST init; 42 43 AST expr; 43 44 mixin SimpleClass; 44 45 } 45 46 46 47 class FuncallExpression : AST 47 48 { ................................................................................ 65 66 template EasyAST() 66 67 { 67 68 template genEast(T) 68 69 { T genEast(P...)(P ps) { return new T(LexPosition.dummy, ps); } } 69 70 70 71 alias genEast!StrLiteral strl; 71 72 alias genEast!IntLiteral intl; 72 - auto fun(string[] xs, AST ps) { return genEast!FunLiteral(xs,ps); } 73 + auto fun(string[] xs, AST ps) { return genEast!FunLiteral(xs,ps); } // to help type inference of D 73 74 alias genEast!VarExpression var; 74 75 alias genEast!LetExpression let; 75 76 alias genEast!FuncallExpression call; 76 77 }

Modified polemy/lex.d from [50586221a28fd499] to [cc80329bc2ab2034].

153 153 this.current = (current is null ? readNext() : current); 154 154 } 155 155 156 156 public static { 157 157 bool isSpace (dchar c) { return std.ctype.isspace(c)!=0; } 158 158 bool isSymbol (dchar c) { return 0x21<=c && c<=0x7f && !std.ctype.isalnum(c) && c!='_' && c!='\''; } 159 159 bool isSSymbol (dchar c) { return !find("()[]{};", c).empty; } 160 - bool isMSymbol (dchar c) { return isSymbol(c) && !isSSymbol(c); } 160 + bool isMSymbol (dchar c) { return isSymbol(c) && !isSSymbol(c) && c!='"' && c!='#'; } 161 161 bool isLetter (dchar c) { return !isSpace(c) && !isSymbol(c); } 162 162 } 163 163 164 164 string readQuoted(const LexPosition pos){char[] buf; return readQuoted(pos,buf);} 165 165 string readQuoted(const LexPosition pos, ref char[] buf) 166 166 { 167 167 if( reader.empty ) ................................................................................ 349 349 assert_eq( lex2.front.str, "5" ); 350 350 lex2.popFront; 351 351 lex3.popFront; 352 352 assert( lex2.empty ); 353 353 assert( !lex3.empty ); 354 354 assert_eq( lex3.front.str, "5" ); 355 355 } 356 + 357 +unittest 358 +{ 359 + auto lex = lexerFromString(`=""`); 360 + assert_eq(lex.front.str, "="); lex.popFront; 361 + assert_eq(lex.front.str, ""); lex.popFront; 362 + assert( lex.empty ); 363 +} 356 364 357 365 /// Forward range for reader character by character, 358 366 /// keeping track of position information and caring \r\n -> \n conversion. 359 367 360 368 private 361 369 struct PositionedReader(CharSeq) 362 370 if( isForwardRange!(CharSeq) && is(ElementType!(CharSeq) == dchar) )

Modified polemy/parse.d from [10baa46251b8a0b6] to [d47e2b014f260d66].

56 56 57 57 AST Body() 58 58 { 59 59 if( lex.empty || !lex.front.quoted && lex.front.str=="}" ) 60 60 return doNothingExpression(); 61 61 62 62 auto pos = lex.front.pos; 63 - if( tryEat("var") ) 63 + string kwd = lex.front.str; 64 + if( tryEat("let") || tryEat("var") || tryEat("def") || tryEat("@") ) 64 65 { 66 + if( kwd == "@" ) 67 + kwd ~= eatId("after @"); 65 68 immutable LexPosition varpos = (lex.empty ? null : lex.front.pos); 66 - string var = eatId("after var"); 67 - eat("=", "after var"); 69 + string var = eatId("after "~kwd); 70 + eat("=", "after "~kwd); 71 + kwd = (kwd[0]=='@' ? kwd : "@val"); 68 72 auto e = E(0); 69 73 if( tryEat(";") && !lex.empty && (lex.front.quoted || (lex.front.str!="}" && lex.front.str!=")")) ) 70 - return new LetExpression(pos, var, e, Body()); 74 + return new LetExpression(pos, var, kwd, e, Body()); 71 75 else 72 - return new LetExpression(pos, var, e, new VarExpression(varpos, var)); 76 + return new LetExpression(pos, var, kwd, e, new VarExpression(varpos, var)); 73 77 } 74 78 else 75 79 { 76 80 auto e = E(0); 77 81 if( tryEat(";") && !lex.empty && (lex.front.quoted || (lex.front.str!="}" && lex.front.str!=")")) ) 78 - return new LetExpression(pos, "_", e, Body()); 82 + return new LetExpression(pos, "_", "@val", e, Body()); 79 83 else 80 84 return e; 81 85 } 82 86 } 83 87 84 88 // [TODO] make customizable from program 85 89 static immutable string[][] operator_perferences = [ ................................................................................ 183 187 return new FuncallExpression(pos, 184 188 new VarExpression(pos, "if"), 185 189 cond, 186 190 new FunLiteral(thenPos, [], th), 187 191 new FunLiteral(elsePos, [], el) 188 192 ); 189 193 } 190 - if( tryEat("fun") ) 194 + if( tryEat("fun") || tryEat("λ") ) 191 195 { 192 196 eat("(", "after fun"); 193 197 string[] params; 194 198 while( !tryEat(")") ) 195 199 { 196 200 params ~= eatId("for function parameter"); 197 201 if( !tryEat(",") ) { ................................................................................ 251 255 { 252 256 mixin EasyAST; 253 257 254 258 assert_eq(parseString(`123`), intl(123)); 255 259 assert_eq(parseString(`"foo"`), strl("foo")); 256 260 assert_eq(parseString(`fun(){1}`), fun([],intl(1))); 257 261 assert_eq(parseString(`fun(x){1}`), fun(["x"],intl(1))); 258 - assert_eq(parseString(`1;2`), let("_",intl(1),intl(2))); 259 - assert_eq(parseString(`1;2;`), let("_",intl(1),intl(2))); 260 - assert_eq(parseString(`var x=1;2`), let("x",intl(1),intl(2))); 261 - assert_eq(parseString(`var x=1;2;`), let("x",intl(1),intl(2))); 262 - assert_eq(parseString(`var x=1`), let("x",intl(1),var("x"))); 263 - assert_eq(parseString(`var x=1;`), let("x",intl(1),var("x"))); 262 + assert_eq(parseString(`λ(){1}`), fun([],intl(1))); 263 + assert_eq(parseString(`λ(x){1}`), fun(["x"],intl(1))); 264 + assert_eq(parseString(`1;2`), let("_","@val",intl(1),intl(2))); 265 + assert_eq(parseString(`1;2;`), let("_","@val",intl(1),intl(2))); 266 + assert_eq(parseString(`let x=1;2`), let("x","@val",intl(1),intl(2))); 267 + assert_eq(parseString(`var x=1;2;`), let("x","@val",intl(1),intl(2))); 268 + assert_eq(parseString(`def x=1`), let("x","@val",intl(1),var("x"))); 269 + assert_eq(parseString(`@val x=1;`), let("x","@val",intl(1),var("x"))); 270 + assert_eq(parseString(`@typ x="#int";`), let("x","@typ",strl("#int"),var("x"))); 264 271 assert_eq(parseString(`f(1,2)`), call(var("f"),intl(1),intl(2))); 265 272 assert_eq(parseString(`if(1){2}`), call(var("if"),intl(1),fun([],intl(2)),fun([],intl(178)))); 266 273 assert_eq(parseString(`if(1){2}else{3}`), call(var("if"),intl(1),fun([],intl(2)),fun([],intl(3)))); 267 274 assert_eq(parseString(`if(1){}else{3}()()`), 268 275 call(call(call(var("if"),intl(1),fun([],intl(178)),fun([],intl(3)))))); 269 276 assert_eq(parseString(`1+2*3`), call(var("+"),intl(1),call(var("*"),intl(2),intl(3)))); 270 277 assert_eq(parseString(`(1+2)*3`), call(var("*"),call(var("+"),intl(1),intl(2)),intl(3))); 271 278 assert_eq(parseString(`1*(2+3)`), call(var("*"),intl(1),call(var("+"),intl(2),intl(3)))); 272 279 assert_eq(parseString(`1*2+3`), call(var("+"),call(var("*"),intl(1),intl(2)),intl(3))); 273 280 274 281 assert_eq(parseString(` 275 - var x = 100; #comment 276 - var y = 200; #comment!!!!! 282 + let x = 100; #comment 283 + let y = 200; #comment!!!!! 277 284 x+y 278 285 `), 279 - let("x", intl(100), let("y", intl(200), call(var("+"), var("x"), var("y")))) 286 + let("x", "@val", intl(100), let("y", "@val", intl(200), call(var("+"), var("x"), var("y")))) 280 287 ); 281 288 282 289 assert_eq(parseString(` 283 290 var fac = fun(x){ if(x <= 1) {1} else {x*fac(x-1)} }; 284 291 fac(10) 285 292 `), 286 - let("fac", fun(["x"], 293 + let("fac", "@val", fun(["x"], 287 294 call(var("if"), 288 295 call(var("<="), var("x"), intl(1)), 289 296 fun([], intl(1)), 290 297 fun([], call(var("*"), var("x"), call(var("fac"),call(var("-"),var("x"),intl(1))))) 291 298 )), 292 299 call(var("fac"),intl(10)) 293 300 ) ................................................................................ 294 301 ); 295 302 } 296 303 297 304 unittest 298 305 { 299 306 assert_throw!ParseException(parseString(`1+`)); 300 307 assert_throw!ParseException(parseString(`1+2}`)); 301 - assert_throw!ParseException(parseString(`var "x"`)); 308 + assert_throw!ParseException(parseString(`let "x"`)); 302 309 assert_throw!ParseException(parseString(`var`)); 303 - assert_throw!ParseException(parseString(`var x ==`)); 310 + assert_throw!ParseException(parseString(`@val x ==`)); 304 311 assert_throw!ParseException(parseString(`if(){1}`)); 305 312 assert_throw!ParseException(parseString(`f(`)); 306 313 }

Modified polemy/value.d from [ac6802f569d2081c] to [b8f99f303d4d3a98].

2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Runtime data structures for Polemy programming language. 6 6 */ 7 7 module polemy.value; 8 8 import polemy._common; 9 -import polemy.lex : LexPosition; 10 -import std.stdio; 9 +import polemy.lex; 11 10 12 -class PolemyRuntimeException : Exception 11 +/// Raised when something went wrong in runtime 12 + 13 +class RuntimeException : Exception 13 14 { 14 - this(string msg) { super(msg); } 15 + const LexPosition pos; 16 + 17 + this( const LexPosition pos, string msg ) 18 + { super(sprintf!"%s [%s]"(msg, pos)); this.pos = pos; } 19 + this( string msg ) { super(msg); this.pos = null; } 15 20 } 21 + 22 +/// Runtime values of Polemy 16 23 17 24 abstract class Value 18 25 { 19 26 } 20 27 21 -class UndefinedValue : Value 22 -{ 23 - mixin SimpleConstructor; 24 - mixin SimpleCompare; 25 - override string toString() const { return "(undefined)"; } 26 -} 27 - 28 28 class IntValue : Value 29 29 { 30 30 BigInt data; 31 + 31 32 mixin SimpleConstructor; 32 33 mixin SimpleCompare; 33 - override string toString() const { 34 - return std.bigint.toDecimalString(cast(BigInt)data); 35 - } 34 + override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); } 36 35 } 37 36 38 37 class StrValue : Value 39 38 { 40 39 string data; 40 + 41 41 mixin SimpleConstructor; 42 42 mixin SimpleCompare; 43 43 override string toString() const { return data; } 44 44 } 45 45 46 46 class FunValue : Value 47 47 { 48 48 Value delegate(immutable LexPosition pos, Value[]) data; 49 + 49 50 mixin SimpleConstructor; 50 - Value call(immutable LexPosition pos, Value[] args) { return data(pos,args); } 51 + alias data call; 51 52 override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); } 52 53 } 53 -import std.stdio; 54 -class Context 54 + 55 +/// Layer ID 56 + 57 +alias string Layer; 58 + 59 +/// Context (variable environment) 60 +/// Simlar to prototype chain of ECMAScript etc. 61 +/// But extended with the notion of "Layer" 62 + 63 +class Table : Value 55 64 { 56 - Context parent; 57 - Value[string] table; 58 - this(Context parent = null) { this.parent = parent; } 65 + enum Kind {PropagateSet, NotPropagateSet}; 66 + 67 + this( Table proto=null, Kind k = Kind.PropagateSet ) 68 + { this.prototype = proto; this.kind = k; } 59 69 60 - void add(string i, Value v) 70 + void set(string i, Layer lay, Value v) 61 71 { 62 - table[i] = v; 72 + if( !setIfExist(i, lay, v) ) 73 + data[i][lay] = v; 63 74 } 64 75 65 - Value opIndex(string i) 76 + Value get(string i, Layer lay) 66 77 { 67 - if( i in table ) 68 - return table[i]; 69 - if( parent is null ) 70 - throw new PolemyRuntimeException(sprintf!"variable %s not found"(i)); 71 - return parent[i]; 78 + if( i in data ) 79 + return data[i][lay]; 80 + if( prototype is null ) 81 + throw new RuntimeException(sprintf!"variable %s not found"(i)); 82 + return prototype.get(i, lay); 72 83 } 73 84 74 - void opIndexAssign(Value v, string i) 85 +private: 86 + Table prototype; 87 + Kind kind; 88 + Value[Layer][string] data; 89 + 90 + bool setIfExist(string i, Layer lay, Value v) 75 91 { 76 - if( i in table ) 77 - return table[i] = v; 78 - if( parent is null ) 79 - throw new PolemyRuntimeException(sprintf!"variable %s not found"(i)); 80 - return parent[i] = v; 92 + if( i in data ) 93 + { 94 + data[i][lay] = v; 95 + return true; 96 + } 97 + if( kind==Kind.PropagateSet && prototype !is null ) 98 + return prototype.setIfExist(i, lay, v); 99 + return false; 81 100 } 82 101 } 102 + 103 +unittest 104 +{ 105 + Table c0 = new Table; 106 + Table c01 = new Table(c0, Table.Kind.NotPropagateSet); 107 + Table c012 = new Table(c01, Table.Kind.PropagateSet); 108 + Table c013 = new Table(c01, Table.Kind.PropagateSet); 109 + 110 + assert_nothrow( c012.set("x", "@val", new IntValue(BigInt(12))) ); 111 + assert_throw!RuntimeException( c013.get("x", "@val") ); 112 + assert_nothrow( c013.set("x", "@val", new IntValue(BigInt(13))) ); 113 + assert_eq( c013.get("x", "@val"), new IntValue(BigInt(13)) ); 114 + assert_eq( c012.get("x", "@val"), new IntValue(BigInt(12)) ); 115 + assert_throw!RuntimeException( c01.get("x", "@val") ); 116 + 117 + assert_nothrow( c01.set("y", "@val", new IntValue(BigInt(1))) ); 118 + assert_eq( c013.get("y", "@val"), new IntValue(BigInt(1)) ); 119 + assert_eq( c012.get("y", "@val"), new IntValue(BigInt(1)) ); 120 + assert_eq( c01.get("y", "@val"), new IntValue(BigInt(1)) ); 121 + 122 + assert_nothrow( c0.set("z", "@val", new IntValue(BigInt(0))) ); 123 + assert_eq( c013.get("z", "@val"), new IntValue(BigInt(0)) ); 124 + assert_eq( c012.get("z", "@val"), new IntValue(BigInt(0)) ); 125 + assert_eq( c01.get("z", "@val"), new IntValue(BigInt(0)) ); 126 + assert_eq( c0.get("z", "@val"), new IntValue(BigInt(0)) ); 127 + 128 + assert_nothrow( c012.set("y", "@val", new IntValue(BigInt(444))) ); 129 + assert_eq( c013.get("y", "@val"), new IntValue(BigInt(444)) ); 130 + assert_eq( c012.get("y", "@val"), new IntValue(BigInt(444)) ); 131 + assert_eq( c01.get("y", "@val"), new IntValue(BigInt(444)) ); 132 + 133 + assert_nothrow( c012.set("z", "@val", new IntValue(BigInt(555))) ); 134 + assert_eq( c013.get("z", "@val"), new IntValue(BigInt(0)) ); 135 + assert_eq( c012.get("z", "@val"), new IntValue(BigInt(555)) ); 136 + assert_eq( c01.get("z", "@val"), new IntValue(BigInt(0)) ); 137 + assert_eq( c0.get("z", "@val"), new IntValue(BigInt(0)) ); 138 + 139 + // [TODO] define the semantics and test @layers 140 +}