230 lines
9.5 KiB
C#
230 lines
9.5 KiB
C#
|
using System.Reflection.Metadata.Ecma335;
|
||
|
|
||
|
namespace KumiScript.Interpreter
|
||
|
{
|
||
|
public class MathPrimitives
|
||
|
{
|
||
|
public static NumberExpression Plus(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
decimal acc = 0;
|
||
|
for (int i = 0; i < argl.Count; i++)
|
||
|
{
|
||
|
NumberExpression? argin = argl[i] as NumberExpression;
|
||
|
if (argin is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
acc += argin.GetValueAsFloat();
|
||
|
}
|
||
|
|
||
|
return NumberFactory.NormalizeFloat(acc);
|
||
|
}
|
||
|
|
||
|
public static NumberExpression Minus(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count == 0)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? argn0 = argl[0] as NumberExpression;
|
||
|
if (argn0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
decimal acc = argn0.GetValueAsFloat();
|
||
|
if (argl.Count == 1)
|
||
|
return NumberFactory.NormalizeFloat(1 - acc);
|
||
|
|
||
|
for (int i = 1; i < argl.Count; i++)
|
||
|
{
|
||
|
NumberExpression? argin = argl[i] as NumberExpression;
|
||
|
if (argin is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
acc -= argin.GetValueAsFloat();
|
||
|
}
|
||
|
return NumberFactory.NormalizeFloat(acc);
|
||
|
}
|
||
|
|
||
|
public static NumberExpression Times(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count < 2)
|
||
|
throw new InterpreterInvalidInvocationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
decimal f = arg0.GetValueAsFloat();
|
||
|
for (int i = 1; i < argl.Count; i++)
|
||
|
{
|
||
|
NumberExpression? argn = argl[i] as NumberExpression;
|
||
|
if (argn is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
f *= argn.GetValueAsFloat();
|
||
|
}
|
||
|
return NumberFactory.NormalizeFloat(f);
|
||
|
}
|
||
|
|
||
|
public static NumberExpression DividedBy(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return NumberFactory.NormalizeFloat(arg0.GetValueAsFloat() / arg1.GetValueAsFloat());
|
||
|
}
|
||
|
|
||
|
public static NumberExpression Modulus(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return NumberFactory.NormalizeFloat(arg0.GetValueAsFloat() % arg1.GetValueAsFloat());
|
||
|
}
|
||
|
|
||
|
public static Expression GreaterThan(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return arg0.GetValueAsFloat() > arg1.GetValueAsFloat() ? TrueExpression.GetInstance() : NilExpression.GetInstance();
|
||
|
}
|
||
|
public static Expression LessThan(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return arg0.GetValueAsFloat() < arg1.GetValueAsFloat() ? TrueExpression.GetInstance() : NilExpression.GetInstance();
|
||
|
}
|
||
|
|
||
|
public static Expression LessThanEquals(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return arg0.GetValueAsFloat() <= arg1.GetValueAsFloat() ? TrueExpression.GetInstance() : NilExpression.GetInstance();
|
||
|
}
|
||
|
|
||
|
public static Expression GreaterThanEquals(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.EvalMembers(env);
|
||
|
if (argl.Count != 2)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
NumberExpression? arg0 = argl[0] as NumberExpression;
|
||
|
if (arg0 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression? arg1 = argl[1] as NumberExpression;
|
||
|
if (arg1 is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
return arg0.GetValueAsFloat() >= arg1.GetValueAsFloat() ? TrueExpression.GetInstance() : NilExpression.GetInstance();
|
||
|
}
|
||
|
|
||
|
public static Expression PlusPlus(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.GetMembers();
|
||
|
if (argl.Count != 1)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
SymbolExpression? binding = argl[0] as SymbolExpression;
|
||
|
if (binding is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
Symbol name = binding.GetSymbol();
|
||
|
Expression val = env.Lookup(name);
|
||
|
NumberExpression? num = val as NumberExpression;
|
||
|
if (num is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression nump = NumberFactory.NormalizeFloat(num.GetValueAsFloat() + 1);
|
||
|
env.RedefineSymbol(name, nump);
|
||
|
return nump;
|
||
|
}
|
||
|
|
||
|
public static Expression MinusMinus(ListExpression args, Environment env)
|
||
|
{
|
||
|
List<Expression> argl = args.GetMembers();
|
||
|
if (argl.Count != 1)
|
||
|
throw new InterpreterInvalidApplicationException();
|
||
|
|
||
|
SymbolExpression? binding = argl[0] as SymbolExpression;
|
||
|
if (binding is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
Symbol name = binding.GetSymbol();
|
||
|
Expression val = env.Lookup(name);
|
||
|
NumberExpression? num = val as NumberExpression;
|
||
|
if (num is null)
|
||
|
throw new InterpreterTypingException();
|
||
|
|
||
|
NumberExpression nump = NumberFactory.NormalizeFloat(num.GetValueAsFloat() - 1);
|
||
|
env.RedefineSymbol(name, nump);
|
||
|
return nump;
|
||
|
}
|
||
|
|
||
|
public static Environment RegisterPrimitives(Environment outer)
|
||
|
{
|
||
|
Environment result = new Environment(outer);
|
||
|
result.AddSymbol(new Symbol("+"), new ProcedureExpression(new PrimitiveProcedure(Plus)));
|
||
|
result.AddSymbol(new Symbol("-"), new ProcedureExpression(new PrimitiveProcedure(Minus)));
|
||
|
result.AddSymbol(new Symbol("*"), new ProcedureExpression(new PrimitiveProcedure(Times)));
|
||
|
result.AddSymbol(new Symbol("/"), new ProcedureExpression(new PrimitiveProcedure(DividedBy)));
|
||
|
result.AddSymbol(new Symbol("%"), new ProcedureExpression(new PrimitiveProcedure(Modulus)));
|
||
|
result.AddSymbol(new Symbol(">"), new ProcedureExpression(new PrimitiveProcedure(GreaterThan)));
|
||
|
result.AddSymbol(new Symbol("<"), new ProcedureExpression(new PrimitiveProcedure(LessThan)));
|
||
|
result.AddSymbol(new Symbol("<="), new ProcedureExpression(new PrimitiveProcedure(LessThanEquals)));
|
||
|
result.AddSymbol(new Symbol(">="), new ProcedureExpression(new PrimitiveProcedure(GreaterThanEquals)));
|
||
|
result.AddSymbol(new Symbol("++!"), new ProcedureExpression(new PrimitiveProcedure(PlusPlus)));
|
||
|
result.AddSymbol(new Symbol("--!"), new ProcedureExpression(new PrimitiveProcedure(MinusMinus)));
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
}
|