public ErlangExpression Parse(string code)
        {
            var expression   = ErlangSyntaxNode.ParseExpression(new TokenBuffer(ErlangToken.Tokenize(new TextBuffer(code))));
            var compiledExpr = ErlangExpression.Compile(expression);

            return(compiledExpr);
        }
Exemple #2
0
 public ErlangBinaryExpression(ErlangExpression left, ErlangExpression right, ErlangOperatorKind op)
 {
     Left     = left;
     Right    = right;
     Operator = op;
     Left.SetParent(this);
     Right.SetParent(this);
 }
Exemple #3
0
 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);
     }
 }
Exemple #4
0
        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"));
        }
Exemple #5
0
 public ErlangListExpression(ErlangExpression[] elements, ErlangExpression tail)
 {
     Elements = elements;
     Tail     = tail;
     foreach (var elem in Elements)
     {
         elem.SetParent(this);
     }
     if (Tail != null)
     {
         Tail.SetParent(this);
     }
 }
Exemple #6
0
 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);
     }
 }
Exemple #7
0
        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);
        }
Exemple #8
0
 public ErlangUnaryExpression(ErlangExpression expression, ErlangOperatorKind op)
 {
     Expression = expression;
     Operator   = op;
 }
Exemple #9
0
 public ErlangGuardClauseExpression(ErlangExpression expression, bool isAnd)
 {
     Expression = expression;
     IsAnd      = isAnd;
     Expression.SetParent(this);
 }
Exemple #10
0
 internal void SetParent(ErlangExpression parent, bool isLastChild = false)
 {
     Parent      = parent;
     IsLastChild = isLastChild;
 }
Exemple #11
0
        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));
 }
Exemple #13
0
        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);
        }