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 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 +}