using System;
using System.Collections.Generic;
namespace DtxCS.DataTypes
{
///
/// The most basic element of dta.
///
public class DataAtom : DataNode
{
DataType type;
string sData;
int iData;
float fData;
///
/// The type of this Atom.
///
public override DataType Type => type;
public override DataNode Evaluate() => this;
///
/// The value of this Atom.
///
public int Int
{
get
{
if (type == DataType.INT)
return iData;
else throw new Exception("Data is not int");
}
}
///
/// The value of this Atom.
///
public float Float
{
get
{
if (type == DataType.FLOAT)
return fData;
else throw new Exception("Data is not float");
}
}
///
/// The value of this Atom.
///
public string String
{
get
{
if (type == DataType.STRING)
return sData;
else throw new Exception("Data is not string");
}
}
///
/// Construct an Atom whose value is a string or symbol.
///
/// The value assigned to this atom.
public DataAtom(string data)
{
type = DataType.STRING;
sData = data.Replace("\\q", "\"");
}
///
/// Construct an Atom whose value is an integer.
///
///
public DataAtom(int data)
{
type = DataType.INT;
iData = data;
}
///
/// Construct an Atom whose value is a floating-point value.
///
///
public DataAtom(float data)
{
type = DataType.FLOAT;
fData = data;
}
///
/// The string representation of this Atom.
///
public override string Name => ToString(true);
private string ToString(bool name)
{
string ret = "";
switch (type)
{
case DataType.STRING:
ret += name ? sData : "\"" + sData.Replace("\"", "\\\"") + "\"";
break;
case DataType.INT:
ret += iData.ToString();
break;
case DataType.FLOAT:
// Even though the format string uses a dot, it gets changed to a comma on some locales
// unless you give ToString the invariant culture.
ret += fData.ToString("0.0#", System.Globalization.NumberFormatInfo.InvariantInfo);
break;
}
return ret;
}
///
/// Returns the string representation of this Atom.
///
///
public override string ToString() => ToString(false);
}
public class DataVariable : DataNode
{
static Dictionary vars = new Dictionary();
public override string Name { get; }
public override string ToString() => Name;
public override DataType Type => DataType.VARIABLE;
public DataNode Value { get; set; }
public override DataNode Evaluate() => Value;
public static DataVariable Var(string name)
{
DataVariable ret;
if (!vars.TryGetValue(name, out ret))
vars.Add(name, ret = new DataVariable(name, new DataAtom(0)));
return ret;
}
///
/// Makes a data variable. Scoping not implemented because we're not an interpreter.
/// Don't give this the $.
///
///
private DataVariable(string name, DataNode value)
{
Name = "$" + name;
Value = value;
}
}
public class DataSymbol : DataNode
{
static Dictionary symbols = new Dictionary();
public static DataSymbol Symbol(string value)
{
DataSymbol ret;
if (!symbols.TryGetValue(value, out ret))
symbols.Add(value, ret = new DataSymbol(value));
return ret;
}
public override string Name => value;
public override DataNode Evaluate() => this;
public override DataType Type => DataType.SYMBOL;
private string value;
private bool quote;
private DataSymbol(string value)
{
this.value = value;
foreach(var c in value)
{
// TODO: Is this right?
if(c == ' ' || c == '\r' || c == '\n' || c == '\t'
|| c == '(' || c == ')' || c == '{' || c == '}'
|| c == '[' || c == ']')
{
quote = true;
break;
}
}
}
public override string ToString() => quote ? $"'{Name}'" : Name;
}
}