Diff
Not logged in

Differences From Artifact [ac6802f569d2081c]:

To Artifact [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 +}