Code/Systems/VNScript/Value.cs
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
namespace VNScript;
public abstract record Value
{
public const char GlobalPrefix = '$';
public virtual Value Evaluate( IEnvironment environment )
{
return this;
}
public delegate Value FunctionMapping( IEnvironment environment, params Value[] values );
/// <summary>
/// Represents a null value, that is the absence of a value.
/// </summary>
public record NoneValue : Value
{
private NoneValue() { }
public static readonly NoneValue None = new();
}
/// <summary>
/// Represents symbols, that is anything that isn't a number or a string and hasn't been dereferenced to a variable yet
/// </summary>
public record VariableReferenceValue( string Name ) : Value
{
public override Value Evaluate( IEnvironment environment )
{
if ( GlobalEnvironment.Map.VariableSet().Contains( Name ) )
{
return GlobalEnvironment.Map.GetVariable( Name );
}
if ( environment.VariableSet().Contains( Name ) )
{
return environment.GetVariable( Name );
}
if ( BooleanValue.BooleanMap.TryGetValue( Name, out var value ) )
{
return new BooleanValue( value );
}
if ( BuiltinFunctions.Builtins.TryGetValue( Name, out var builtin ) )
{
return builtin;
}
throw new UndefinedVariableException( Name );
}
}
/// <summary>
/// Represents a true or false value, a boolean.
/// </summary>
public record BooleanValue( bool Boolean ) : Value
{
public override string ToString()
{
return Boolean.ToString().ToLower();
}
public static Dictionary<string, bool> BooleanMap { get; } = new()
{
["true"] = true,
["false"] = false,
};
}
public record StringValue( string Text ) : Value
{
public override string ToString()
{
return Text;
}
}
public record NumberValue( decimal Number ) : Value
{
public override string ToString()
{
return Number.ToString( CultureInfo.CurrentCulture );
}
}
public record FunctionValue( FunctionMapping Function ) : Value;
public record ListValue( SParen ValueList ) : Value
{
public override Value Evaluate( IEnvironment environment )
{
if ( ValueList.Count <= 0 )
{
return this;
}
var firstValue = ValueList[0];
if ( firstValue is VariableReferenceValue variableRefValue )
{
firstValue = variableRefValue.Evaluate( environment );
}
if ( firstValue is FunctionValue functionValue )
{
return functionValue.Function( environment, ValueList.Skip( 1 ).ToArray() );
}
return this;
}
public override string ToString()
{
return ValueList.ToString() ?? "[]";
}
}
public bool IsTruthy()
{
return this switch
{
BooleanValue boolean => boolean.Boolean,
NumberValue number => number.Number != 0,
NoneValue => false,
_ => true
};
}
}