protected override ErlangValue EvaluateLocal(ErlangProcess process, string functionName, ErlangValue[] parameters) { var function = GetFunction(functionName, parameters.Length); if (function == null) { return(new ErlangError("no matching function found")); } if (!function.IsPublic) { return(new ErlangError("no matching function found")); } var overload = function.GetFunctionOverload(process, parameters); if (overload != null) { return(overload.Evaluate(process)); } else { return(new ErlangError("no matching function found")); } }
public override ErlangValue Evaluate(ErlangProcess process) { ErlangValue result = null; bool evaluated = false; var parameters = Parameters.Select(p => p.Evaluate(process)).ToArray(); if (Module == null) { var module = GetModule(); if (module != null) { // try to execute from the current module if (module.FunctionExistsInternal(Function, parameters.Length)) { result = module.EvaluateInternal(process, Function, parameters); evaluated = true; } } } if (!evaluated) { // couldn't execute from this module, kick it back to the ErlangProcess to find the function result = process.Evaluate(Module, Function, parameters); } return(result); }
public override ErlangValue Evaluate(ErlangProcess process) { var value = Expression.Evaluate(process); if (value.Kind == ErlangValueKind.Error) { return(value); } foreach (var branch in Branches) { process.CallStack.CurrentFrame.IncreaseScopeLevel(); if (ErlangBinder.TryBindParameter(branch.Pattern, value, process.CallStack.CurrentFrame)) { if (branch.Guard == null || ErlangAtom.IsTrue(branch.Guard.Evaluate(process))) { var result = branch.Evaluate(process); process.CallStack.CurrentFrame.DecreaseScopeLevel(); return(result); } } process.CallStack.CurrentFrame.DecreaseScopeLevel(); } return(new ErlangError("bad match on case")); }
public override ErlangValue Evaluate(ErlangProcess process) { var result = Expression.Evaluate(process); if (result.Kind == ErlangValueKind.Error) { return(result); } switch (Operator) { case ErlangOperatorKind.Plus: return(ErlangValue.Multiply(result, ErlangNumber.One)); case ErlangOperatorKind.Minus: return(ErlangValue.Multiply(result, ErlangNumber.NegativeOne)); case ErlangOperatorKind.Not: return(ErlangValue.Not(result)); case ErlangOperatorKind.BNot: if (result.Kind == ErlangValueKind.Number) { return(ErlangNumber.BNot((ErlangNumber)result)); } else { return(new ErlangError("not integral")); } default: return(new ErlangError(string.Format("Invalid unary operator: {0}", Operator))); } }
public ErlangValue Evaluate(ErlangProcess process, string functionName, ErlangValue[] parameters) { ErlangValue error = null; if (functionName == "module_info") { if (parameters.Length == 0) { return(ModuleInfo); } else if (parameters.Length == 1) { if (parameters[0].Kind == ErlangValueKind.Atom) { var text = ((ErlangAtom)parameters[0]).Name; if (text == "functions") { return(AllFunctions); } else { // find matching tuple var list = ModuleInfo; while (list != null && list.Value != null) { Debug.Assert(list.Value is ErlangTuple); var tuple = (ErlangTuple)list.Value; Debug.Assert(tuple.Airity == 2); Debug.Assert(tuple.Values[0].Kind == ErlangValueKind.Atom); if (((ErlangAtom)tuple.Values[0]).Name == text) { Debug.Assert(tuple.Values[1].Kind == ErlangValueKind.List); return(tuple.Values[1]); } list = list.Tail as ErlangList; } return(new ErlangError("no matching tuple item")); } } else { error = new ErlangError("no matching function"); } } else { error = new ErlangError("no matching function"); } } error = error ?? parameters.FirstOrDefault(p => p.Kind == ErlangValueKind.Error); return(error ?? EvaluateLocal(process, functionName, parameters)); }
protected override ErlangValue EvaluateLocal(ErlangProcess process, string function, ErlangValue[] parameters) { MethodInfo methodInfo; if (functionMap.TryGetValue(Tuple.Create(function, parameters.Length), out methodInfo)) { return((ErlangValue)methodInfo.Invoke(Target, parameters)); } return(new ErlangError("no matching function found")); }
public ErlangReplFunctions(ErlangProcess process) { this.process = process; foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods) { var parameters = methodInfo.GetParameters(); var methodAttrs = methodInfo.GetCustomAttributes(typeof(ErlangFunctionAttribute), false).OfType <ErlangFunctionAttribute>().ToArray(); if (parameters.All(p => p.ParameterType == typeof(ErlangExpression)) && methodInfo.ReturnType == typeof(ErlangValue) && methodAttrs.Length == 1) { functionMap.Add(Tuple.Create(methodAttrs[0].Name, parameters.Length), methodInfo); } } }
public override ErlangValue Evaluate(ErlangProcess process) { var values = new ErlangValue[Elements.Length]; for (int i = 0; i < Elements.Length; i++) { var value = Elements[i].Evaluate(process); if (value.Kind == ErlangValueKind.Error) { return(value); } values[i] = value; } return(new ErlangTuple(values)); }
public ErlangFunctionOverloadExpression GetFunctionOverload(ErlangProcess process, ErlangValue[] parameters) { Debug.Assert(parameters.Length == Airity); for (int i = 0; i < Overloads.Length; i++) { if (Overloads[i].TryBindParameters(process, parameters)) { var guard = Overloads[i].Guard; if (guard == null || ErlangAtom.IsTrue(guard.Evaluate(process))) { return(Overloads[i]); } } } return(null); }
public override ErlangValue Evaluate(ErlangProcess process) { var values = new ErlangValue[Elements.Length]; for (int i = 0; i < Elements.Length; i++) { var value = Elements[i].Evaluate(process); if (value.Kind == ErlangValueKind.Error) { return(value); } values[i] = value; } var list = new ErlangList(values, Tail == null ? null : Tail.Evaluate(process)); return(list); }
public static bool TryBindParameters(ErlangProcess process, ErlangExpression[] parameters, ErlangValue[] values) { if (parameters.Length != values.Length) { return(false); } var frame = process.CallStack.CurrentFrame; for (int i = 0; i < values.Length; i++) { if (!ErlangBinder.TryBindParameter(parameters[i], values[i], frame, true)) { return(false); } } return(true); }
internal ErlangValue EvaluateInternal(ErlangProcess process, string functionName, ErlangValue[] parameters) { ErlangValue result; var function = GetFunction(functionName, parameters.Length); process.CallStack.Push(new ErlangStackFrame(Name, functionName, parameters.Length)); var overload = function.GetFunctionOverload(process, parameters); if (overload != null) { result = overload.Evaluate(process); } else { result = new ErlangError("no matching function found"); } process.CallStack.Pop(); return(result); }
public override ErlangValue Evaluate(ErlangProcess process) { Debug.Assert(Clauses.Length > 0); var isAnd = Clauses[0].IsAnd; var result = ErlangAtom.IsTrue(Clauses[0].Evaluate(process)); for (int i = 1; i < Clauses.Length; i++) { var next = Clauses[i].Evaluate(process); if (isAnd) { result = result && ErlangAtom.IsTrue(Clauses[i].Evaluate(process)); } else { result = result || ErlangAtom.IsTrue(Clauses[i].Evaluate(process)); } isAnd = Clauses[i].IsAnd; } return(result ? ErlangAtom.True : ErlangAtom.False); }
public bool TryBindParameters(ErlangProcess process, ErlangValue[] values) { return(TryBindParameters(process, Parameters, values)); }
protected abstract ErlangValue EvaluateLocal(ErlangProcess process, string functionName, ErlangValue[] parameters);
public ErlangBifs(ErlangProcess process) { Process = process; }
public override ErlangValue Evaluate(ErlangProcess process) { // variable assignment or pattern match if (Operator == ErlangOperatorKind.Equals) { // first evaluate the right side var right = Right.Evaluate(process); if (right.Kind == ErlangValueKind.Error) { return(right); } // now match to the left if (ErlangBinder.TryBindParameter(Left, right, process.CallStack.CurrentFrame)) { return(right); } else { return(new ErlangError("bad match")); } } var left = Left.Evaluate(process); if (left.Kind == ErlangValueKind.Error) { return(left); } if (IsShortCircuitOperator(Operator)) { switch (Operator) { case ErlangOperatorKind.AndAlso: if (ErlangAtom.IsTrue(left)) { return(Right.Evaluate(process)); } else { return(ErlangAtom.False); } case ErlangOperatorKind.OrElse: if (ErlangAtom.IsTrue(left)) { return(left); } else { return(Right.Evaluate(process)); } default: throw new ArgumentException("invalid operator"); } } else { var right = Right.Evaluate(process); if (right.Kind == ErlangValueKind.Error) { return(right); } switch (Operator) { case ErlangOperatorKind.Plus: return(ErlangValue.Add(left, right)); case ErlangOperatorKind.Minus: return(ErlangValue.Subtract(left, right)); case ErlangOperatorKind.Asterisk: return(ErlangValue.Multiply(left, right)); case ErlangOperatorKind.Slash: return(ErlangValue.Divide(left, right)); case ErlangOperatorKind.And: return(ErlangValue.And(left, right)); case ErlangOperatorKind.Or: return(ErlangValue.Or(left, right)); case ErlangOperatorKind.Less: return(ErlangValue.Less(left, right)); case ErlangOperatorKind.EqualsLess: return(ErlangValue.LessEquals(left, right)); case ErlangOperatorKind.Greater: return(ErlangValue.Greater(left, right)); case ErlangOperatorKind.GreaterEquals: return(ErlangValue.GreaterEquals(left, right)); case ErlangOperatorKind.EqualsEquals: return(ErlangValue.EqualsEquals(left, right)); case ErlangOperatorKind.SlashEquals: return(ErlangValue.SlashEquals(left, right)); case ErlangOperatorKind.EqualsColonEquals: return(ErlangValue.EqualsColonEquals(left, right)); case ErlangOperatorKind.EqualsSlashEquals: return(ErlangValue.EqualsSlashEquals(left, right)); case ErlangOperatorKind.PlusPlus: return(ErlangValue.PlusPlus(left, right)); default: throw new ArgumentException("invalid operator"); } } }
public override ErlangValue Evaluate(ErlangProcess process) { var value = process.CallStack.CurrentFrame.GetVariable(Variable); return(value ?? new ErlangError(string.Format("No such variable {0}", Variable))); }
public override ErlangValue Evaluate(ErlangProcess process) { return(Evaluate()); }
public override ErlangValue Evaluate(ErlangProcess process) { return(Expression.Evaluate(process)); }
public ErlangExpressionEvaluator() { Process = new ErlangProcess(); }
public virtual ErlangValue Evaluate(ErlangProcess process) { throw new NotSupportedException(); }
public override ErlangValue Evaluate(ErlangProcess process) { ErlangValue last = null; ErlangExpressionBlockExpression def = this; ErlangCompiledModule module = GetModule(); var children = def.GetChildren(); bool doTailCall = false; do { doTailCall = false; // ensure we're reset from the last loop // evaluate each expression Debug.Assert(children.Length > 0); for (int i = 0; !doTailCall && i < children.Length; i++) { var expression = children[i]; string moduleName = null; ErlangFunctionInvocationExpression function = null; ErlangStackFrame tailCallCandidate = null; if (UseTailCalls && i == children.Length - 1 && expression is ErlangFunctionInvocationExpression && expression.IsLastChild) { // if last expression and it's a function invocation function = (ErlangFunctionInvocationExpression)expression; moduleName = function.Module ?? module.Name; tailCallCandidate = process.CallStack.GetTailCallCandidate( moduleName, function.Function, function.Parameters.Length); doTailCall = tailCallCandidate != null; } if (doTailCall) { // evaluate parameters var evaledParams = new ErlangValue[function.Parameters.Length]; for (int j = 0; j < function.Parameters.Length; j++) { var value = function.Parameters[j].Evaluate(process); if (value.Kind == ErlangValueKind.Error) { return(value); } evaledParams[j] = value; } // prepare new frame var newFrame = new ErlangStackFrame(tailCallCandidate.Module, tailCallCandidate.Function, tailCallCandidate.Airity); process.CallStack.RewindForTailCall(newFrame); // find the new definition var group = module.GetFunction(function.Function, evaledParams.Length); def = group.GetFunctionOverload(process, evaledParams); if (def == null) { return(new ErlangAtom("no_such_tailcall_function")); } children = def.GetChildren(); } else { // not a tailcall, just invoke normally last = children[i].Evaluate(process); if (last.Kind == ErlangValueKind.Error) { return(last); // decrease scope? } } } } while (doTailCall); return(last); }