2024-07-12 00:17:00 +00:00
|
|
|
using KumiScript.Reader;
|
|
|
|
|
2024-01-26 05:37:51 +00:00
|
|
|
namespace KumiScript.Interpreter
|
|
|
|
{
|
|
|
|
public class LispPrimitives
|
|
|
|
{
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Lambda(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
Expression car = args.Car();
|
2024-07-12 00:17:00 +00:00
|
|
|
Expression rest = args.Cdr();
|
2024-01-26 05:37:51 +00:00
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
List<Expression> headl = car.GetMembers();
|
2024-01-26 05:37:51 +00:00
|
|
|
List<Symbol> arg_names = new List<Symbol>();
|
|
|
|
for (int i = 0; i < headl.Count; i++)
|
|
|
|
{
|
2024-07-12 00:17:00 +00:00
|
|
|
arg_names.Add(headl[i].GetSymbol());
|
2024-01-26 05:37:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Expression body = rest.Car();
|
|
|
|
return new ProcedureExpression(new LispProcedure(arg_names, body, env));
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Quote(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
if (argl.Count != 1)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
|
|
|
return argl[0];
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Define(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
if (argl.Count != 2)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
Expression? binding = argl[0];
|
2024-01-26 05:37:51 +00:00
|
|
|
Symbol name = binding.GetSymbol();
|
|
|
|
Expression definition = argl[1].Eval(env);
|
|
|
|
env.AddSymbol(name, definition);
|
|
|
|
return definition;
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Car(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 1)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
2024-07-12 00:17:00 +00:00
|
|
|
|
|
|
|
return argl[0].Car();
|
2024-01-26 05:37:51 +00:00
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Cdr(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 1)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
2024-07-12 00:17:00 +00:00
|
|
|
|
|
|
|
return argl[0].Cdr();
|
2024-01-26 05:37:51 +00:00
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static ProperListExpression Cons(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 2)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
|
|
|
Expression car = argl[0];
|
2024-07-12 00:17:00 +00:00
|
|
|
Expression cdr = argl[1];
|
2024-01-26 05:37:51 +00:00
|
|
|
return cdr.Cons(car);
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Quit(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
System.Environment.Exit(0);
|
|
|
|
return new SymbolExpression(new Symbol("bye"));
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Cond(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
for (int i = 0; i < argl.Count; i ++)
|
|
|
|
{
|
2024-07-12 00:17:00 +00:00
|
|
|
Expression conditional = argl[i];
|
2024-01-26 05:37:51 +00:00
|
|
|
Expression antecedent = conditional.Car();
|
|
|
|
Expression consequent = conditional.Cdr().Car();
|
2024-02-14 06:20:53 +00:00
|
|
|
if (antecedent.Eval(env) != NilExpression.GetInstance())
|
2024-01-26 05:37:51 +00:00
|
|
|
return consequent.Eval(env);
|
|
|
|
}
|
|
|
|
return NilExpression.GetInstance();
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Eq(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 2)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
|
|
|
if (argl[0].Equals(argl[1]))
|
|
|
|
return TrueExpression.GetInstance();
|
|
|
|
|
|
|
|
return NilExpression.GetInstance();
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Set(Expression args, Environment env)
|
2024-01-26 05:37:51 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
if (argl.Count != 2)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
Symbol name = argl[0].GetSymbol();
|
2024-01-26 05:37:51 +00:00
|
|
|
Expression definition = argl[1].Eval(env);
|
|
|
|
env.RedefineSymbol(name, definition);
|
|
|
|
return definition;
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression For(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Progn(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
Expression result = NilExpression.GetInstance();
|
|
|
|
|
|
|
|
foreach (Expression expr in argl)
|
|
|
|
result = expr.Eval(env);
|
2024-07-12 00:17:00 +00:00
|
|
|
|
2024-02-14 06:20:53 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Prog1(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.GetMembers();
|
|
|
|
Expression result = argl.Count > 0 ? argl[0] : NilExpression.GetInstance();
|
|
|
|
|
|
|
|
foreach (Expression expr in argl)
|
|
|
|
expr.Eval(env);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Not(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 1)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
|
|
|
return argl[0] != NilExpression.GetInstance() ? NilExpression.GetInstance() : TrueExpression.GetInstance();
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression Nth(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
List<Expression> argl = args.EvalMembers(env);
|
|
|
|
if (argl.Count != 2)
|
|
|
|
throw new InterpreterInvalidApplicationException();
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
int n = (int) argl[0].GetValueAsFloat();
|
|
|
|
List<Expression> arg1l = argl[1].GetMembers();
|
2024-02-14 06:20:53 +00:00
|
|
|
return n >= 0 && n < arg1l.Count ? arg1l[n] : NilExpression.GetInstance();
|
|
|
|
}
|
|
|
|
|
2024-07-12 00:17:00 +00:00
|
|
|
public static Expression While(Expression args, Environment env)
|
2024-02-14 06:20:53 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-26 05:37:51 +00:00
|
|
|
public static Environment RegisterPrimitives()
|
|
|
|
{
|
|
|
|
Environment result = new Environment();
|
2024-07-12 00:17:00 +00:00
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("lambda"), new ProcedureExpression(new PrimitiveProcedure(Lambda)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("quote"), new ProcedureExpression(new PrimitiveProcedure(Quote)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("define"), new ProcedureExpression(new PrimitiveProcedure(Define)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("car"), new ProcedureExpression(new PrimitiveProcedure(Car)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("cdr"), new ProcedureExpression(new PrimitiveProcedure(Cdr)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("cons"), new ProcedureExpression(new PrimitiveProcedure(Cons)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("quit"), new ProcedureExpression(new PrimitiveProcedure(Quit)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("cond"), new ProcedureExpression(new PrimitiveProcedure(Cond)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("eq"), new ProcedureExpression(new PrimitiveProcedure(Eq)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("set!"), new ProcedureExpression(new PrimitiveProcedure(Set)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("for"), new ProcedureExpression(new PrimitiveProcedure(For)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("progn"), new ProcedureExpression(new PrimitiveProcedure(Progn)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("not"), new ProcedureExpression(new PrimitiveProcedure(Not)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("prog1"), new ProcedureExpression(new PrimitiveProcedure(Prog1)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("nth"), new ProcedureExpression(new PrimitiveProcedure(Nth)));
|
|
|
|
result.AddSymbol(SymbolTable.GetInstance().FromString("while"), new ProcedureExpression(new PrimitiveProcedure(While)));
|
2024-01-26 05:37:51 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|