public ErlangExpression Parse(string code) { var expression = ErlangSyntaxNode.ParseExpression(new TokenBuffer(ErlangToken.Tokenize(new TextBuffer(code)))); var compiledExpr = ErlangExpression.Compile(expression); return(compiledExpr); }
public ErlangBinaryExpression(ErlangExpression left, ErlangExpression right, ErlangOperatorKind op) { Left = left; Right = right; Operator = op; Left.SetParent(this); Right.SetParent(this); }
public ErlangCaseExpression(ErlangExpression expression, ErlangCaseBranchExpression[] branches) { Expression = expression; Branches = branches; Expression.SetParent(this); for (int i = 0; i < Branches.Length; i++) { Branches[i].SetParent(this); } }
public ErlangValue Forget(ErlangExpression expression) { if (expression is ErlangVariableExpression) { process.CallStack.CurrentFrame.UnsetVariable(((ErlangVariableExpression)expression).Variable); return(new ErlangAtom("ok")); } return(new ErlangError("not a variable")); }
public ErlangListExpression(ErlangExpression[] elements, ErlangExpression tail) { Elements = elements; Tail = tail; foreach (var elem in Elements) { elem.SetParent(this); } if (Tail != null) { Tail.SetParent(this); } }
public ErlangCaseBranchExpression(ErlangExpression pattern, ErlangGuardExpression guard, ErlangExpression[] body) { Pattern = pattern; Guard = guard; Body = body; Pattern.SetParent(this); if (Guard != null) { Guard.SetParent(this); } for (int i = 0; i < Body.Length; i++) { Body[i].SetParent(this); } }
public ErlangValue TryEvaluate(ErlangExpression expression) { if (expression is ErlangFunctionInvocationExpression) { var func = (ErlangFunctionInvocationExpression)expression; if (func.Module == null) { var key = Tuple.Create(func.Function, func.Parameters.Length); if (functionMap.ContainsKey(key)) { return((ErlangValue)functionMap[key].Invoke(this, func.Parameters)); } } } return(null); }
public ErlangUnaryExpression(ErlangExpression expression, ErlangOperatorKind op) { Expression = expression; Operator = op; }
public ErlangGuardClauseExpression(ErlangExpression expression, bool isAnd) { Expression = expression; IsAnd = isAnd; Expression.SetParent(this); }
internal void SetParent(ErlangExpression parent, bool isLastChild = false) { Parent = parent; IsLastChild = isLastChild; }
public static ErlangModule Compile(ErlangModuleSyntax syntax) { var module = new ErlangCompiledModule(); // get the module's name var atom = syntax.Attributes.OfType <ErlangAttributeSyntax>().Single(at => at.Name.Text == "module").Parameters.Single().Value as ErlangAtomSyntax; module.Name = atom.Atom.Text; // get visibility var publicFunctions = new HashSet <Tuple <string, int> >(); var exportAll = (from at in syntax.Attributes.OfType <ErlangAttributeSyntax>() where at.Name.Text == "compile" && at.Parameters.Count == 1 let param = at.Parameters[0] where param.Value is ErlangAtomSyntax && ((ErlangAtomSyntax)param.Value).Atom.Text == "export_all" select true).Any(b => b); if (!exportAll) { foreach (var functionReference in from at in syntax.Attributes.OfType <ErlangAttributeSyntax>() where at.Name.Text == "export" && at.Parameters.Count == 1 let param = at.Parameters[0] where param.Value is ErlangListRegularSyntax let list = (ErlangListRegularSyntax)param.Value from item in list.Items where item.Item is ErlangFunctionReferenceSyntax select(ErlangFunctionReferenceSyntax) item.Item) { publicFunctions.Add(Tuple.Create(functionReference.Function.Text, (int)functionReference.Airity.IntegerValue)); } } // compile functions var functionList = new List <ErlangTuple>(); var exportedFunctions = new List <ErlangTuple>(); foreach (var group in syntax.FunctionGroups) { var key = Tuple.Create(group.Name, group.Airity); functionList.Add(new ErlangTuple(new ErlangAtom(group.Name), new ErlangNumber(group.Airity))); var function = (ErlangFunctionGroupExpression)ErlangExpression.Compile(group); function.Module = module; function.IsPublic = exportAll || publicFunctions.Contains(key); if (function.IsPublic) { exportedFunctions.Add(new ErlangTuple(new ErlangAtom(group.Name), new ErlangNumber(group.Airity))); } module.AddFunction(key.Item1, key.Item2, function); } functionList.Add(new ErlangTuple(new ErlangAtom("module_info"), new ErlangNumber(0))); functionList.Add(new ErlangTuple(new ErlangAtom("module_info"), new ErlangNumber(1))); exportedFunctions.Add(new ErlangTuple(new ErlangAtom("module_info"), new ErlangNumber(0))); exportedFunctions.Add(new ErlangTuple(new ErlangAtom("module_info"), new ErlangNumber(1))); module.AllFunctions = new ErlangList(functionList.ToArray()); module.ModuleInfo = new ErlangList( new ErlangTuple(new ErlangAtom("exports"), new ErlangList(exportedFunctions.ToArray())), new ErlangTuple(new ErlangAtom("imports"), new ErlangList()), // always empty. may be removed in future versions new ErlangTuple(new ErlangAtom("attributes"), new ErlangList()), // TODO: populate attributes new ErlangTuple(new ErlangAtom("compile"), new ErlangList()) // TODO: process compile options ); return(module); }
public ErlangValue Evaluate(ErlangExpression expression) { return(expression.Evaluate(Process)); }
public static bool TryBindParameter(ErlangExpression expression, ErlangValue value, ErlangStackFrame frame, bool bindBinary = false) { var type = expression.GetType(); if (bindBinary && type == typeof(ErlangBinaryExpression)) { var bin = (ErlangBinaryExpression)expression; switch (bin.Operator) { case ErlangOperatorKind.Equals: // if the right is a variable, bind to the left then to the right if (bin.Right is ErlangVariableExpression) { if (TryBindParameter(bin.Left, value, frame)) { return(TryBindParameter(bin.Right, value, frame)); } } break; // TODO: bind list concatenation '++', etc. } return(false); } else if (type == typeof(ErlangVariableExpression)) { var variable = (ErlangVariableExpression)expression; if (variable.Variable == "_") { // always matches, never binds return(true); } else { var current = frame.GetVariable(variable.Variable); if (current == null) { // set the value frame.SetVariable(variable.Variable, value); return(true); } else { // ensure the same value return(current.Equals(value)); } } } else if (type == typeof(ErlangAtomExpression) && value.Kind == ErlangValueKind.Atom) { return(((ErlangAtomExpression)expression).Atom == ((ErlangAtom)value).Name); } else if (type == typeof(ErlangConstantExpression) && value.Kind == ErlangValueKind.Number) { return(((ErlangConstantExpression)expression).Value == (ErlangNumber)value); } else if (type == typeof(ErlangTupleExpression) && value.Kind == ErlangValueKind.Tuple) { var tuple1 = (ErlangTupleExpression)expression; var tuple2 = (ErlangTuple)value; if (tuple1.Elements.Length == tuple2.Airity) { for (int j = 0; j < tuple1.Elements.Length; j++) { if (!TryBindParameter(tuple1.Elements[j], tuple2.Values[j], frame)) { return(false); } } return(true); } } else if (type == typeof(ErlangListExpression) && value.Kind == ErlangValueKind.List) { // TODO: support list comprehensions var expressionList = (ErlangListExpression)expression; var ErlangList = (ErlangList)value; if (ErlangList.Value == null) { // if the Erlang list is empty, the expression list must be, too return(expressionList.Elements.Length == 0 && expressionList.Tail == null); } // gather Erlang list values var head = ErlangList; int i; for (i = 0; i < expressionList.Elements.Length && head != null && head.Value != null; i++) { if (!TryBindParameter(expressionList.Elements[i], head.Value, frame)) { return(false); } if (head.Tail != null && head.Tail.Kind == ErlangValueKind.List) { head = (ErlangList)head.Tail; } else { head = null; } } if (expressionList.Elements.Length > 0 && i < expressionList.Elements.Length) { // didn't make it through the expression list return(false); } // expressionList.Tail == null and head.Value == null matches if (expressionList.Tail == null) { if (head == null || head.Value == null) { return(true); } else { return(false); } } else { if (head == null) { return(false); } else { return(TryBindParameter(expressionList.Tail, head, frame)); } } } return(false); }