Artifact Content
Not logged in

Artifact 01c119756ed23ca52f2bed9fa082d71e91f61d55


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