Differences From Artifact [ac6802f569d2081c]:
- File
polemy/value.d
- 2010-11-08 08:01:27 - part of checkin [b0d8d7875b] on branch trunk - polemy.runtime renamed into polemy.value. Also, in process of changes to use unittest helpers. (user: kinaba) [annotate]
To Artifact [b8f99f303d4d3a98]:
- File
polemy/value.d
- 2010-11-08 16:40:55 - part of checkin [aa770610d3] on branch trunk - added layered-let (user: kinaba) [annotate]
2 * Authors: k.inaba 2 * Authors: k.inaba
3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/
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.lex : LexPosition; | 9 import polemy.lex;
10 import std.stdio; <
11 10
> 11 /// Raised when something went wrong in runtime
> 12
12 class PolemyRuntimeException : Exception | 13 class RuntimeException : Exception
13 { 14 {
> 15 const LexPosition pos;
> 16
> 17 this( const LexPosition pos, string msg )
> 18 { super(sprintf!"%s [%s]"(msg, pos)); this.pos = pos; }
14 this(string msg) { super(msg); } | 19 this( string msg ) { super(msg); this.pos = null; }
15 } 20 }
> 21
> 22 /// Runtime values of Polemy
16 23
17 abstract class Value 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 class IntValue : Value 28 class IntValue : Value
29 { 29 {
30 BigInt data; 30 BigInt data;
> 31
31 mixin SimpleConstructor; 32 mixin SimpleConstructor;
32 mixin SimpleCompare; 33 mixin SimpleCompare;
33 override string toString() const { <
34 return std.bigint.toDecimalString(cast(BigInt)data); | 34 override string toString() const { return std.bigint.toDecimalString(cas
35 } <
36 } 35 }
37 36
38 class StrValue : Value 37 class StrValue : Value
39 { 38 {
40 string data; 39 string data;
> 40
41 mixin SimpleConstructor; 41 mixin SimpleConstructor;
42 mixin SimpleCompare; 42 mixin SimpleCompare;
43 override string toString() const { return data; } 43 override string toString() const { return data; }
44 } 44 }
45 45
46 class FunValue : Value 46 class FunValue : Value
47 { 47 {
48 Value delegate(immutable LexPosition pos, Value[]) data; 48 Value delegate(immutable LexPosition pos, Value[]) data;
> 49
49 mixin SimpleConstructor; 50 mixin SimpleConstructor;
50 Value call(immutable LexPosition pos, Value[] args) { return data(pos,ar | 51 alias data call;
51 override string toString() const { return sprintf!"(function:%s:%s)"(dat 52 override string toString() const { return sprintf!"(function:%s:%s)"(dat
52 } 53 }
53 import std.stdio; <
> 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
54 class Context | 63 class Table : Value
55 { 64 {
56 Context parent; | 65 enum Kind {PropagateSet, NotPropagateSet};
57 Value[string] table; <
> 66
58 this(Context parent = null) { this.parent = parent; } | 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 {
> 72 if( !setIfExist(i, lay, v) )
62 table[i] = 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 ) | 78 if( i in data )
68 return table[i]; | 79 return data[i][lay];
69 if( parent is null ) | 80 if( prototype is null )
70 throw new PolemyRuntimeException(sprintf!"variable %s no | 81 throw new RuntimeException(sprintf!"variable %s not foun
71 return parent[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 ) | 92 if( i in data )
> 93 {
> 94 data[i][lay] = v;
77 return table[i] = v; | 95 return true;
78 if( parent is null ) <
79 throw new PolemyRuntimeException(sprintf!"variable %s no <
> 96 }
> 97 if( kind==Kind.PropagateSet && prototype !is null )
> 98 return prototype.setIfExist(i, lay, v);
80 return parent[i] = 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 }