/// <summary> /// Evaluates a parsed expression using the specified interpreter input. /// </summary> public static Datum Evaluate(Parser.Expression ParsedExpression, ProgramInput Input) { // Assign all input variables to a position on the stack of the root scope. (Seperates names and values) IVariableStack<Expression> typestack; IMutableVariableStack<Value> datastack; Scope scope; Input.PrepareRootScope(out scope, out datastack, out typestack); // Prepare Expression exp = Expression.Prepare(ParsedExpression, scope, Input); Expression exptype; exp.TypeCheck(typestack, SpaghettiStack<Expression>.Empty(typestack.NextFreeIndex), out exp, out exptype); // Evaluate return new Datum(exp.Evaluate(datastack), exptype); }
private static void _PrepareLambda( List<KeyValuePair<Parser.Expression, string>> Arguments, Parser.Expression Inner, Scope Scope, ProgramInput Input, out Expression ArgumentType, out Expression PreparedInner) { // 0 arg function if (Arguments.Count == 0) { ArgumentType = TupleExpression.Empty; PreparedInner = Prepare(Inner, Scope, Input); return; } // 1 arg function Dictionary<string, int> vars; int argloc = Scope.NextFreeIndex; Scope nscope = new Scope() { NextFreeIndex = argloc + 1, Variables = vars = new Dictionary<string, int>(), Parent = Scope }; if (Arguments.Count == 1) { var kvp = Arguments[0]; if (kvp.Value != null) { vars.Add(kvp.Value, argloc); } ArgumentType = Prepare(kvp.Key, Scope, Input); PreparedInner = Prepare(Inner, nscope, Input); return; } // 2+ arg function Expression[] types = new Expression[Arguments.Count]; for (int t = 0; t < types.Length; t++) { types[t] = Prepare(Arguments[t].Key, Scope, Input); } nscope.NextFreeIndex += types.Length; for (int t = 0; t < Arguments.Count; t++) { string argname = Arguments[t].Value; if (argname != null) { vars.Add(argname, t + argloc + 1); } } ArgumentType = Expression.Tuple(types); PreparedInner = Expression.BreakTuple( argloc + 1, Arguments.Count, Expression.Variable(argloc), Prepare(Inner, nscope, Input)); }
/// <summary> /// Prepares a parsed expression for use. /// </summary> public static Expression Prepare(Parser.Expression Expression, Scope Scope, ProgramInput Input) { // Function call Parser.FunctionCallExpression fce = Expression as Parser.FunctionCallExpression; if (fce != null) { Expression func = Prepare(fce.Function, Scope, Input); if (fce.Arguments.Count == 0) { return new FunctionCallExpression(func, TupleExpression.Empty); } if (fce.Arguments.Count == 1) { return new FunctionCallExpression(func, Prepare(fce.Arguments[0], Scope, Input)); } Expression[] args = new Expression[fce.Arguments.Count]; for (int t = 0; t < args.Length; t++) { args[t] = Prepare(fce.Arguments[t], Scope, Input); } return new FunctionCallExpression(func, new TupleExpression(args)); } // Procedure Parser.ProcedureExpression pe = Expression as Parser.ProcedureExpression; if (pe != null) { return ProcedureExpression.Prepare(pe, Scope, Input); } // Variable Parser.VariableExpression ve = Expression as Parser.VariableExpression; if (ve != null) { return PrepareVariable(ve.Name, Scope); } // Integer liteal Parser.IntegerLiteralExpression ile = Expression as Parser.IntegerLiteralExpression; if (ile != null) { return new ValueExpression(Input.GetIntegerLiteral(ile.Value), Input.IntegerLiteralType); } // Accessor Parser.AccessorExpression ae = Expression as Parser.AccessorExpression; if (ae != null) { return new AccessorExpression(Prepare(ae.Object, Scope, Input), ae.Property); } // Function definition Parser.FunctionDefineExpression fde = Expression as Parser.FunctionDefineExpression; if (fde != null) { Expression argtype; Expression inner; _PrepareLambda(fde.Arguments, fde.Definition, Scope, Input, out argtype, out inner); return new FunctionDefineExpression(Scope.NextFreeIndex, argtype, inner); } // Function type Parser.FunctionTypeExpression fte = Expression as Parser.FunctionTypeExpression; if (fte != null) { // Notice that this is almost exactly the same as a function definition? weird type system, eh? Expression argtype; Expression inner; _PrepareLambda(fte.ArgumentTypes, fte.ReturnType, Scope, Input, out argtype, out inner); return new FunctionDefineExpression(Scope.NextFreeIndex, argtype, inner); } throw new NotImplementedException(); }