addition of primitive procedures
This commit is contained in:
parent
b3363d3f5d
commit
4a2429150d
3 changed files with 325 additions and 106 deletions
|
@ -26,104 +26,6 @@ namespace KumiScript.Interpreter
|
|||
return new ProcedureExpression(new LispProcedure(arg_names, body, env));
|
||||
}
|
||||
|
||||
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 Quote(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.GetMembers();
|
||||
|
@ -207,7 +109,7 @@ namespace KumiScript.Interpreter
|
|||
|
||||
Expression antecedent = conditional.Car();
|
||||
Expression consequent = conditional.Cdr().Car();
|
||||
if (!(antecedent.Eval(env) is NilExpression))
|
||||
if (antecedent.Eval(env) != NilExpression.GetInstance())
|
||||
return consequent.Eval(env);
|
||||
}
|
||||
return NilExpression.GetInstance();
|
||||
|
@ -242,6 +144,93 @@ namespace KumiScript.Interpreter
|
|||
return definition;
|
||||
}
|
||||
|
||||
public static Expression For(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.GetMembers();
|
||||
if (argl.Count != 4)
|
||||
throw new InterpreterInvalidApplicationException();
|
||||
|
||||
Expression init = argl[0];
|
||||
Expression cond = argl[1];
|
||||
Expression step = argl[2];
|
||||
Expression body = argl[3];
|
||||
Expression result = NilExpression.GetInstance();
|
||||
Environment inner = new Environment(env);
|
||||
|
||||
for (init.Eval(inner); cond.Eval(inner) != NilExpression.GetInstance(); step.Eval(inner))
|
||||
result = body.Eval(inner);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Expression Progn(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.GetMembers();
|
||||
Expression result = NilExpression.GetInstance();
|
||||
|
||||
foreach (Expression expr in argl)
|
||||
{
|
||||
result = expr.Eval(env);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Expression Prog1(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.GetMembers();
|
||||
Expression result = argl.Count > 0 ? argl[0] : NilExpression.GetInstance();
|
||||
|
||||
foreach (Expression expr in argl)
|
||||
expr.Eval(env);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Expression Not(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.EvalMembers(env);
|
||||
if (argl.Count != 1)
|
||||
throw new InterpreterInvalidApplicationException();
|
||||
|
||||
return argl[0] != NilExpression.GetInstance() ? NilExpression.GetInstance() : TrueExpression.GetInstance();
|
||||
}
|
||||
|
||||
public static Expression Nth(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.EvalMembers(env);
|
||||
if (argl.Count != 2)
|
||||
throw new InterpreterInvalidApplicationException();
|
||||
|
||||
IntegerExpression? arg0 = argl[0] as IntegerExpression;
|
||||
if (arg0 is null)
|
||||
throw new InterpreterTypingException();
|
||||
|
||||
ListExpression? arg1 = argl[1] as ListExpression;
|
||||
if (arg1 is null)
|
||||
throw new InterpreterTypingException();
|
||||
|
||||
int n = arg0.GetValueAsInt();
|
||||
List<Expression> arg1l = arg1.GetMembers();
|
||||
return n >= 0 && n < arg1l.Count ? arg1l[n] : NilExpression.GetInstance();
|
||||
}
|
||||
|
||||
public static Expression While(ListExpression args, Environment env)
|
||||
{
|
||||
List<Expression> argl = args.GetMembers();
|
||||
if (argl.Count != 2)
|
||||
throw new InterpreterInvalidApplicationException();
|
||||
|
||||
Expression cond = argl[0];
|
||||
Expression body = argl[1];
|
||||
Expression result = NilExpression.GetInstance();
|
||||
Environment inner = new Environment(env);
|
||||
|
||||
while (cond.Eval(inner) != NilExpression.GetInstance())
|
||||
result = body.Eval(inner);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Environment RegisterPrimitives()
|
||||
{
|
||||
Environment result = new Environment();
|
||||
|
@ -253,14 +242,14 @@ namespace KumiScript.Interpreter
|
|||
result.AddSymbol(new Symbol("cons"), new ProcedureExpression(new PrimitiveProcedure(Cons)));
|
||||
result.AddSymbol(new Symbol("quit"), new ProcedureExpression(new PrimitiveProcedure(Quit)));
|
||||
result.AddSymbol(new Symbol("cond"), new ProcedureExpression(new PrimitiveProcedure(Cond)));
|
||||
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("eq"), new ProcedureExpression(new PrimitiveProcedure(Eq)));
|
||||
result.AddSymbol(new Symbol("set!"), new ProcedureExpression(new PrimitiveProcedure(Set)));
|
||||
|
||||
result.AddSymbol(new Symbol("for"), new ProcedureExpression(new PrimitiveProcedure(For)));
|
||||
result.AddSymbol(new Symbol("progn"), new ProcedureExpression(new PrimitiveProcedure(Progn)));
|
||||
result.AddSymbol(new Symbol("not"), new ProcedureExpression(new PrimitiveProcedure(Not)));
|
||||
result.AddSymbol(new Symbol("prog1"), new ProcedureExpression(new PrimitiveProcedure(Prog1)));
|
||||
result.AddSymbol(new Symbol("nth"), new ProcedureExpression(new PrimitiveProcedure(Nth)));
|
||||
result.AddSymbol(new Symbol("while"), new ProcedureExpression(new PrimitiveProcedure(While)));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
230
interpreter/MathPrimitives.cs
Normal file
230
interpreter/MathPrimitives.cs
Normal file
|
@ -0,0 +1,230 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ namespace KumiScript.Interpreter
|
|||
Lexer lexer = new Lexer(_stdin);
|
||||
Parser parser = new Parser(lexer);
|
||||
StreamWriter streamWriter = new StreamWriter(_stdout);
|
||||
Environment top = LispPrimitives.RegisterPrimitives();
|
||||
Environment top = MathPrimitives.RegisterPrimitives(LispPrimitives.RegisterPrimitives());
|
||||
|
||||
while (true) //this thing is ugly but it's just a little test
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue