Ejemplo n.º 1
0
        private ElaJuxtaposition MakeBind(ElaExpression exp)
        {
            var ret = new ElaJuxtaposition
            {
                Target = new ElaNameReference {
                    Name = ">>="
                }
            };

            ret.Parameters.Add(exp);
            ret.Parameters.Add(null);

            ret.SetLinePragma(exp.Line, exp.Column);
            ret.Target.SetLinePragma(exp.Line, exp.Column);

            return(ret);
        }
Ejemplo n.º 2
0
        //Perform an eta expansion for a given expression
        private void EtaExpand(string name, ElaExpression exp, LabelMap map, int args)
        {
            //Here we generate a function which has a provided number of
            //arguments
            if (name != null)
            {
                StartFun(name, args);
            }

            StartSection();
            StartScope(true, exp.Line, exp.Column);
            cw.StartFrame(args);
            var funSkipLabel = cw.DefineLabel();

            cw.Emit(Op.Br, funSkipLabel);
            var address = cw.Offset;

            if (exp.Type != ElaNodeType.Equation)
            {
                CompileExpression(exp, map, Hints.None, null);
            }
            else
            {
                CompileFunction((ElaEquation)exp, map);
            }

            //Functions are curried so generate a call for each argument
            for (var i = 0; i < args; i++)
            {
                cw.Emit(Op.Call);
            }

            cw.Emit(Op.Ret);
            frame.Layouts.Add(new MemoryLayout(currentCounter, cw.FinishFrame(), address));
            EndSection();
            EndScope();

            if (name != null)
            {
                EndFun(frame.Layouts.Count - 1);
            }

            cw.MarkLabel(funSkipLabel);
            cw.Emit(Op.PushI4, args);
            cw.Emit(Op.Newfun, frame.Layouts.Count - 1);
        }
Ejemplo n.º 3
0
        private void ProcessBinding(ElaEquationSet block, ElaEquation bid, ElaExpression left, ElaExpression right)
        {
            bid.Left  = left;
            bid.Right = right;

            if (bindings.Peek() == unit)
            {
                block.Equations.Add(bid);
                return;
            }

            var fName = default(String);

            if (right != null && left.Type == ElaNodeType.Juxtaposition && !left.Parens)
            {
                var fc = (ElaJuxtaposition)left;

                if (fc.Target.Type == ElaNodeType.NameReference)
                {
                    fName = fc.Target.GetName();
                }
            }

            if (fName != null)
            {
                var lastB = bindings.Peek();

                if (lastB != null && ((ElaJuxtaposition)lastB.Left).Target.GetName() == fName)
                {
                    lastB.Next = bid;
                }
                else
                {
                    block.Equations.Add(bid);
                }

                bindings.Pop();
                bindings.Push(bid);
            }
            else
            {
                block.Equations.Add(bid);
            }
        }
Ejemplo n.º 4
0
        //Compiles any given expression as lazy, can be used to automatically generate thunks
        //as well as to compile an explicit lazy literal.
        private ExprData CompileLazyExpression(ElaExpression exp, LabelMap map, Hints hints)
        {
            Label    funSkipLabel;
            int      address;
            LabelMap newMap;

            CompileFunctionProlog(null, 1, exp.Line, exp.Column, out funSkipLabel, out address, out newMap);
            var ed = CompileExpression(exp, newMap, Hints.Scope | Hints.FunBody, null);

            CompileFunctionEpilog(null, 1, address, funSkipLabel);

            if (ed.Type == DataKind.BuiltinError)
            {
                cw.Emit(Op.Api, 18);
            }

            cw.Emit(Op.Newlazy);

            return(default(ExprData));
        }
Ejemplo n.º 5
0
        //Checks if we need to force a constructor parameter.
        private bool IsBang(ElaExpression exp)
        {
            if (exp.Type == ElaNodeType.NameReference && ((ElaNameReference)exp).Bang)
            {
                return(true);
            }
            else if (exp.Type == ElaNodeType.Juxtaposition)
            {
                var j = (ElaJuxtaposition)exp;

                if (j.Parameters[0].Type == ElaNodeType.NameReference &&
                    ((ElaNameReference)j.Parameters[0]).Bang)
                {
                    return(true);
                }

                return(false);
            }

            return(false);
        }
Ejemplo n.º 6
0
        //Includes a module reference (used for user references, Prelude and Components module).
        private CodeFrame IncludeModule(string alias, string name, string dllName, string[] path,
                                        int line, int col, bool reqQual, ElaExpression exp, bool addVar, bool noPrelude)
        {
            var modIndex = frame.HandleMap.Count;
            var modRef   = new ModuleReference(frame, name, dllName, path, line, col, reqQual, modIndex);

            modRef.NoPrelude = noPrelude;
            frame.AddReference(alias, modRef);

            //Handles are filled by linker for module indexing at run-time
            frame.HandleMap.Add(-1);

            if (exp != null)
            {
                AddLinePragma(exp);
            }

            cw.Emit(Op.Runmod, modIndex);
            var addr = -1;

            if (addVar)
            {
                //Create a variable and bind to it module instance
                cw.Emit(Op.Newmod, modIndex);
                addr = AddVariable(alias, exp, ElaVariableFlags.Module | ElaVariableFlags.Private, modIndex);
            }

            //An event is handled by linker and a module is compiled/deserialized
            var ev = new ModuleEventArgs(modRef);

            comp.OnModuleInclude(ev);
            refs.Add(ev.Frame);

            if (addr != -1)
            {
                PopVar(addr);
            }

            return(ev.Frame);
        }
Ejemplo n.º 7
0
        //Compiles xs parameters, can be used in all cases where xs creation is needed.
        private void CompileTupleParameters(ElaExpression v, List <ElaExpression> pars, LabelMap map)
        {
            //Optimize xs creates for a case of pair (a single op typeId is used).
            if (pars.Count == 2)
            {
                CompileExpression(pars[0], map, Hints.None, v);
                CompileExpression(pars[1], map, Hints.None, v);
                AddLinePragma(v);
                cw.Emit(Op.Newtup_2);
            }
            else
            {
                AddLinePragma(v);
                cw.Emit(Op.Newtup, pars.Count);

                for (var i = 0; i < pars.Count; i++)
                {
                    CompileExpression(pars[i], map, Hints.None, v);
                    cw.Emit(Op.Tupcons, i);
                }
            }
        }
Ejemplo n.º 8
0
        //Builds a lists of all variables that are declared in the given pattern.
        private void ExtractPatternNames(ElaExpression pat, List <String> names)
        {
            switch (pat.Type)
            {
            case ElaNodeType.LazyLiteral:
            {
                //This whole method is used to extract names before making a
                //pattern lazy, so we need to extract all names here as well,
                //because this lazy literal will be compiled strict anyway (because
                //the whole pattern is lazy already).
                var vp = (ElaLazyLiteral)pat;
                ExtractPatternNames(vp.Expression, names);
            }
            break;

            case ElaNodeType.UnitLiteral:     //Idle
                break;

            case ElaNodeType.As:
            {
                var asPat = (ElaAs)pat;
                names.Add(asPat.Name);
                ExtractPatternNames(asPat.Expression, names);
            }
            break;

            case ElaNodeType.Primitive:     //Idle
                break;

            case ElaNodeType.NameReference:
            {
                var vexp = (ElaNameReference)pat;

                if (!vexp.Uppercase)         //Uppercase is constructor
                {
                    names.Add(vexp.Name);
                }
            }
            break;

            case ElaNodeType.RecordLiteral:
            {
                var rexp = (ElaRecordLiteral)pat;

                foreach (var e in rexp.Fields)
                {
                    if (e.FieldValue != null)
                    {
                        ExtractPatternNames(e.FieldValue, names);
                    }
                }
            }
            break;

            case ElaNodeType.TupleLiteral:
            {
                var texp = (ElaTupleLiteral)pat;

                foreach (var e in texp.Parameters)
                {
                    ExtractPatternNames(e, names);
                }
            }
            break;

            case ElaNodeType.Placeholder:     //Idle
                break;

            case ElaNodeType.Juxtaposition:
            {
                var hexp = (ElaJuxtaposition)pat;

                foreach (var e in hexp.Parameters)
                {
                    ExtractPatternNames(e, names);
                }
            }
            break;

            case ElaNodeType.ListLiteral:
            {
                var l = (ElaListLiteral)pat;

                if (l.HasValues())
                {
                    foreach (var e in l.Values)
                    {
                        ExtractPatternNames(e, names);
                    }
                }
            }
            break;
            }
        }
Ejemplo n.º 9
0
 //Tests if a given expression is a name reference of a placeholder (_).
 private bool IsSimplePattern(ElaExpression exp)
 {
     return(exp.Type == ElaNodeType.NameReference || exp.Type == ElaNodeType.Placeholder);
 }
Ejemplo n.º 10
0
        //Compile a given expression as a pattern. If match fails proceed to failLab.
        private void CompilePattern(int sysVar, ElaExpression exp, Label failLab, bool allowBang, bool forceStrict)
        {
            AddLinePragma(exp);

            switch (exp.Type)
            {
            case ElaNodeType.LazyLiteral:
            {
                var n = (ElaLazyLiteral)exp;

                //Normally this flag is set when everything is already compiled as lazy.
                if (forceStrict)
                {
                    CompilePattern(sysVar, n.Expression, failLab, allowBang, forceStrict);
                }
                else
                {
                    CompileLazyPattern(sysVar, exp, allowBang);
                }
            }
            break;

            case ElaNodeType.FieldReference:
            {
                //We treat this expression as a constructor with a module alias
                var n     = (ElaFieldReference)exp;
                var fn    = n.FieldName;
                var alias = n.TargetObject.GetName();
                PushVar(sysVar);

                if (n.TargetObject.Type != ElaNodeType.NameReference)
                {
                    AddError(ElaCompilerError.InvalidPattern, n, FormatNode(n));
                }
                else
                {
                    EmitSpecName(alias, "$$$$" + fn, n, ElaCompilerError.UndefinedName);
                }

                cw.Emit(Op.Skiptag);
                cw.Emit(Op.Br, failLab);
            }
            break;

            case ElaNodeType.NameReference:
            {
                //Irrefutable pattern, always binds expression to a name, unless it is
                //a constructor pattern
                var n = (ElaNameReference)exp;

                //Bang pattern are only allowed in constructors and functions
                if (n.Bang && !allowBang)
                {
                    AddError(ElaCompilerError.BangPatternNotValid, exp, FormatNode(exp));
                    AddHint(ElaCompilerHint.BangsOnlyFunctions, exp);
                }

                if (n.Uppercase)         //This is a constructor
                {
                    if (sysVar != -1)
                    {
                        PushVar(sysVar);
                    }

                    EmitSpecName(null, "$$$$" + n.Name, n, ElaCompilerError.UndefinedName);

                    //This op codes skips one offset if an expression
                    //on the top of the stack has a specified tag.
                    cw.Emit(Op.Skiptag);
                    cw.Emit(Op.Br, failLab);
                }
                else
                {
                    var newV = false;
                    var addr = AddMatchVariable(n.Name, n, out newV);

                    //This is a valid situation, it means that the value is
                    //already on the top of the stack.
                    if (sysVar > -1 && newV)
                    {
                        PushVar(sysVar);
                    }

                    if (n.Bang)
                    {
                        cw.Emit(Op.Force);
                    }

                    //The binding is already done, so just idle.
                    if (newV)
                    {
                        PopVar(addr);
                    }
                }
            }
            break;

            case ElaNodeType.UnitLiteral:
            {
                //Unit pattern is redundant, it is essentially the same as checking
                //the type of an expression which is what we do here.
                PushVar(sysVar);
                cw.Emit(Op.Force);
                cw.Emit(Op.PushI4, (Int32)ElaTypeCode.Unit);
                cw.Emit(Op.Ctype);

                //Types are not equal, proceed to fail.
                cw.Emit(Op.Brfalse, failLab);
            }
            break;

            case ElaNodeType.Primitive:
            {
                var n = (ElaPrimitive)exp;

                //Compare a given value with a primitive
                PushVar(sysVar);
                PushPrimitive(n, n.Value);
                cw.Emit(Op.Cneq);

                //Values not equal, proceed to fail.
                cw.Emit(Op.Brtrue, failLab);
            }
            break;

            case ElaNodeType.As:
            {
                var n = (ElaAs)exp;
                CompilePattern(sysVar, n.Expression, failLab, allowBang, false /*forceStrict*/);
                var newV = false;
                var addr = AddMatchVariable(n.Name, n, out newV);
                PushVar(sysVar);
                PopVar(addr);
            }
            break;

            case ElaNodeType.Placeholder:
                //This is a valid situation, it means that the value is
                //already on the top of the stack. Otherwise - nothing have to be done.
                if (sysVar == -1)
                {
                    cw.Emit(Op.Pop);
                }
                break;

            case ElaNodeType.RecordLiteral:
            {
                var n = (ElaRecordLiteral)exp;
                CompileRecordPattern(sysVar, n, failLab, allowBang);
            }
            break;

            case ElaNodeType.TupleLiteral:
            {
                var n = (ElaTupleLiteral)exp;
                CompileTuplePattern(sysVar, n, failLab, allowBang);
            }
            break;

            case ElaNodeType.Juxtaposition:
            {
                //An infix pattern, currently the only case is head/tail pattern.
                var n = (ElaJuxtaposition)exp;
                CompileComplexPattern(sysVar, n, failLab, allowBang);
            }
            break;

            case ElaNodeType.ListLiteral:
            {
                var n = (ElaListLiteral)exp;

                //We a have a nil pattern '[]'
                if (!n.HasValues())
                {
                    PushVar(sysVar);
                    cw.Emit(Op.Isnil);
                    cw.Emit(Op.Brfalse, failLab);
                }
                else
                {
                    //We don't want to write the same compilation logic twice,
                    //so here we transform a list literal into a chain of function calls, e.g.
                    //[1,2,3] goes to 1::2::3::[] with a mandatory nil at the end.
                    var           len  = n.Values.Count;
                    ElaExpression last = ElaListLiteral.Empty;
                    var           fc   = default(ElaJuxtaposition);

                    //Loops through all elements in literal backwards
                    for (var i = 0; i < len; i++)
                    {
                        var nn = n.Values[len - i - 1];
                        fc = new ElaJuxtaposition();
                        fc.SetLinePragma(nn.Line, nn.Column);
                        fc.Parameters.Add(nn);
                        fc.Parameters.Add(last);
                        last = fc;
                    }

                    //Now we can compile it as head/tail pattern
                    CompilePattern(sysVar, fc, failLab, allowBang, false /*forceStrict*/);
                }
            }
            break;

            default:
                AddError(ElaCompilerError.InvalidPattern, exp, FormatNode(exp));
                break;
            }
        }
Ejemplo n.º 11
0
        //This method contains main compilation logic for 'match' expressions and for 'try' expressions.
        //This method only supports a single pattern per entry.
        //A 'mexp' (matched expression) parameter can be null and is used for additional validation only.
        private void CompileSimpleMatch(IEnumerable <ElaEquation> bindings, LabelMap map, Hints hints, ElaExpression mexp)
        {
            ValidateOverlapSimple(map, bindings, mexp);

            var failLab = cw.DefineLabel();
            var endLab  = cw.DefineLabel();

            //We need to remembers the first set of system addresses because we will have
            //to push them manually for the entries other than first.
            var firstSys = -1;
            var first    = true;

            //Loops through all bindings
            //For the first iteration we assume that all values are already on stack.
            //For the next iteration we manually push all values.
            foreach (var b in bindings)
            {
                //Each match entry starts a lexical scope
                StartScope(false, b.Line, b.Column);

                //For second+ entries we put a label where we would jump if a previous
                //pattern fails
                if (!first)
                {
                    cw.MarkLabel(failLab);
                    failLab = cw.DefineLabel();
                }

                var p      = b.Left;
                var sysVar = -1;

                //We apply an optimization if a we have a name reference (only for the first iteration).
                if (p.Type == ElaNodeType.NameReference && first)
                {
                    sysVar = AddVariable(p.GetName(), p, ElaVariableFlags.Parameter, -1);
                }
                else
                {
                    sysVar = AddVariable(); //Create an unnamed system variable
                }
                //This is not the first entry, so we have to push values first
                if (!first)
                {
                    PushVar(firstSys);
                }

                PopVar(sysVar);

                //We have to remember addresses calculated in a first iteration
                //to be able to push them once again in a second iteration.
                if (first)
                {
                    firstSys = sysVar;
                }

                CompilePattern(sysVar, p, failLab, false /*allowBang*/, false /*forceStrict*/);
                first = false;

                //Compile entry expression
                if (b.Right == null)
                {
                    AddError(ElaCompilerError.InvalidMatchEntry, b.Left, FormatNode(b));
                }
                else
                {
                    CompileExpression(b.Right, map, Hints.None, b);
                }

                //Close current scope
                EndScope();

                //If everything is OK skip through 'fail' clause
                cw.Emit(Op.Br, endLab);
            }

            //We fall here if all patterns have failed
            cw.MarkLabel(failLab);

            //If this hints is set than we generate a match for a 'try'
            //(exception handling) block. Instead of MatchFailed we need
            //to rethrow an original exception. Block 'try' always have
            //just a single expression to match, therefore firstSys[0] is
            //pretty safe here.
            if ((hints & Hints.Throw) == Hints.Throw)
            {
                PushVar(firstSys);
                cw.Emit(Op.Rethrow);
            }
            else
            {
                cw.Emit(Op.Failwith, (Int32)ElaRuntimeError.MatchFailed);
            }

            //Happy path for match
            cw.MarkLabel(endLab);
            cw.Emit(Op.Nop);
        }
Ejemplo n.º 12
0
 //The same as FormatNode(ElaExpression,bool) but always formats AST not in non-compact manner.
 private string FormatNode(ElaExpression exp)
 {
     return(FormatNode(exp, false));
 }
Ejemplo n.º 13
0
 public static TreeNode Plain(this TreeNode par, ElaExpression exp)
 {
     return(Element(par, exp, "", exp.ToString(), "Function", "{0}{1}"));
 }
Ejemplo n.º 14
0
 private void AddError(ElaCompilerError error, ElaExpression exp, params object[] args)
 {
     AddError(error, exp.Line, exp.Column, args);
 }
Ejemplo n.º 15
0
 public static TreeNode Name(this TreeNode par, ElaExpression exp, object data, string title = "name")
 {
     return(Element(par, exp, title, data, "Field", "{1} ({0})"));
 }
Ejemplo n.º 16
0
        //Performs a type check and throws and error if the type is not as expected.
        //This method assumes that a value to be checked is on the top of the stack.
        private ScopeVar TypeCheckConstructor(string cons, string prefix, string name, ElaExpression par, bool force)
        {
            var sv = EmitSpecName(prefix, "$$" + name, par, ElaCompilerError.UndefinedType);

            TypeCheckConstructorAllStack(cons, force);
            return(sv);
        }
Ejemplo n.º 17
0
 //Generates a line pragma and remembers a provided location
 //via lastLine and lastColumn class fields.
 private void AddLinePragma(ElaExpression exp)
 {
     lastLine   = exp.Line;
     lastColumn = exp.Column;
     pdb.AddLineSym(cw.Offset, exp.Line, exp.Column);
 }
Ejemplo n.º 18
0
        //Adding all variables from pattern as NoInit's. This method recursively walks
        //all patterns. Currently we don't associate any additional metadata or flags
        //(except of NoInit) with variables inferred in such a way.
        private void AddPatternVariables(ElaExpression pat)
        {
            switch (pat.Type)
            {
            case ElaNodeType.LazyLiteral:
            {
                //Not all forms of lazy patterns are supported,
                //but it is easier to process them anyways. Errors will be caught
                //during pattern compilation.
                var vp = (ElaLazyLiteral)pat;
                AddPatternVariables(vp.Expression);
            }
            break;

            case ElaNodeType.UnitLiteral:     //Idle
                break;

            case ElaNodeType.As:
            {
                var asPat = (ElaAs)pat;
                AddVariable(asPat.Name, asPat, ElaVariableFlags.NoInit, -1);
                AddPatternVariables(asPat.Expression);
            }
            break;

            case ElaNodeType.Primitive:     //Idle
                break;

            case ElaNodeType.NameReference:
            {
                var vexp = (ElaNameReference)pat;

                if (!vexp.Uppercase)         //Uppercase is constructor
                {
                    AddVariable(vexp.Name, vexp, ElaVariableFlags.NoInit, -1);
                }
            }
            break;

            case ElaNodeType.RecordLiteral:
            {
                var rexp = (ElaRecordLiteral)pat;

                foreach (var e in rexp.Fields)
                {
                    if (e.FieldValue != null)
                    {
                        AddPatternVariables(e.FieldValue);
                    }
                }
            }
            break;

            case ElaNodeType.TupleLiteral:
            {
                var texp = (ElaTupleLiteral)pat;

                foreach (var e in texp.Parameters)
                {
                    AddPatternVariables(e);
                }
            }
            break;

            case ElaNodeType.Placeholder:     //Idle
                break;

            case ElaNodeType.Juxtaposition:
            {
                var hexp = (ElaJuxtaposition)pat;

                foreach (var e in hexp.Parameters)
                {
                    AddPatternVariables(e);
                }
            }
            break;

            case ElaNodeType.ListLiteral:     //Idle
            {
                var l = (ElaListLiteral)pat;

                if (l.HasValues())
                {
                    foreach (var e in l.Values)
                    {
                        AddPatternVariables(e);
                    }
                }
            }
            break;
            }
        }
Ejemplo n.º 19
0
 public static TreeNode Literal(this TreeNode par, ElaExpression exp, ElaTypeCode typeCode, object data)
 {
     return(Element(par, exp, TCF.GetShortForm(typeCode), data, "Literal", "{1} ({0})"));
 }
Ejemplo n.º 20
0
        private void PopulateNodes(TreeNode par, ElaExpression exp)
        {
            if (exp == null)
            {
                return;
            }

            switch (exp.Type)
            {
            case ElaNodeType.DebugPoint:
                var @deb    = (ElaDebugPoint)exp;
                var debNode = par.Simple(exp, String.Format("trace: {0}", @deb.Data));
                if (@deb.Expression != null)
                {
                    PopulateNodes(debNode, @deb.Expression);
                }
                break;

            case ElaNodeType.DoNotation:
                var @do    = (ElaDoNotation)exp;
                var doNode = par.Simple(@do, "do");

                foreach (var st in @do.Statements)
                {
                    var stNode = doNode.Simple(st, "statement");
                    PopulateNodes(stNode, st);
                }
                break;

            case ElaNodeType.DoAssignment:
                var @ass = (ElaDoAssignment)exp;
                par.Simple(@ass, String.Format("{0} <- {1}", @ass.Left, @ass.Right));
                break;

            case ElaNodeType.As:
                var @as = (ElaAs)exp;
                par.Control(@as, "as", @as.Name);
                break;

            case ElaNodeType.Builtin:
                var @built = (ElaBuiltin)exp;
                par.Control(@built, "built-in", @built.Kind.ToString());
                break;

            case ElaNodeType.ClassInstance:
                var @inst = (ElaClassInstance)exp;

                while (@inst != null)
                {
                    var instNode = par.Simple(@inst, "instance " +
                                              (String.IsNullOrEmpty(@inst.TypeClassPrefix) ? @inst.TypeClassName : String.Format("{0}.{1}", @inst.TypeClassName, @inst.TypeClassPrefix)) + "( " +
                                              (String.IsNullOrEmpty(@inst.TypePrefix) ? @inst.TypeName : String.Format("{0}.{1}", @inst.TypePrefix, @inst.TypeName)) + " )");
                    PopulateNodes(instNode, @inst.Where);
                    @inst = @inst.And;
                }
                break;

            case ElaNodeType.ClassMember:
                var @mem = (ElaClassMember)exp;
                par.Plain(@mem);
                break;

            case ElaNodeType.Comprehension:
                var @comp    = (ElaComprehension)exp;
                var compNode = par.Simple(@comp, @comp.Lazy ? "lazy comprehension" : "comprehension");
                PopulateNodes(compNode, @comp.Generator);
                break;

            case ElaNodeType.Condition:
                var @cond       = (ElaCondition)exp;
                var condNode    = par.Simple(@cond, "if");
                var condExpNode = condNode.Simple(@cond.Condition, "condition");
                PopulateNodes(condExpNode, @cond.Condition);
                var trueExpNode = condNode.Simple(@cond.True, "true");
                PopulateNodes(trueExpNode, @cond.True);
                var falseExpNode = condNode.Simple(@cond.False, "false");
                PopulateNodes(falseExpNode, @cond.False);
                break;

            case ElaNodeType.Context:
                var @ctx       = (ElaContext)exp;
                var ctxNode    = par.Simple(@ctx, "context");
                var ctxSetNode = ctxNode.Simple(@ctx, "set context");
                PopulateNodes(ctxSetNode, @ctx.Context);
                if (@ctx.Expression != null)
                {
                    var ctxObjNode = ctxNode.Simple(@ctx, "expression");
                    PopulateNodes(ctxObjNode, @ctx.Expression);
                }
                break;

            case ElaNodeType.Equation:
                var @eq        = (ElaEquation)exp;
                var eqNode     = par.Simple(@eq, "equation");
                var eqLeftNode = eqNode.Simple(@eq.Left, "left");
                PopulateNodes(eqLeftNode, @eq.Left);
                if (@eq.Right != null)
                {
                    var eqRightNode = eqNode.Simple(@eq.Right, "right");
                    PopulateNodes(eqRightNode, @eq.Right);
                }
                break;

            case ElaNodeType.EquationSet:
                var @eqs    = (ElaEquationSet)exp;
                var eqsNode = par.Simple(@eqs, "equation set");
                foreach (var e in @eqs.Equations)
                {
                    PopulateNodes(eqsNode, e);
                }
                break;

            case ElaNodeType.FieldDeclaration:
                var @fldDec    = (ElaFieldDeclaration)exp;
                var fldDecNode = par.Simple(@fldDec, "field " + @fldDec.FieldName);
                PopulateNodes(fldDecNode, @fldDec.FieldValue);
                break;

            case ElaNodeType.FieldReference:
                var @fld    = (ElaFieldReference)exp;
                var fldNode = par.Simple(@fld, "field " + @fld.FieldName);
                PopulateNodes(fldNode, @fld.TargetObject);
                break;

            case ElaNodeType.Generator:
                var @gen          = (ElaGenerator)exp;
                var genNode       = par.Simple(@gen, "generator");
                var genTargetNode = genNode.Simple(@gen.Target, "target");
                PopulateNodes(genTargetNode, @gen.Target);
                var genPatternNode = genNode.Simple(@gen.Pattern, "pattern");
                PopulateNodes(genPatternNode, @gen.Pattern);
                var genGuardNode = genNode.Simple(@gen.Guard, "guard");
                PopulateNodes(genGuardNode, @gen.Guard);
                var genBodyNode = genNode.Simple(@gen.Body, "body");
                PopulateNodes(genBodyNode, @gen.Body);
                break;

            case ElaNodeType.Header:
                var @head = (ElaHeader)exp;
                var attrs = String.Empty;
                if ((@head.Attributes & ElaVariableFlags.Private) == ElaVariableFlags.Private)
                {
                    attrs += "private ";
                }
                if ((@head.Attributes & ElaVariableFlags.Qualified) == ElaVariableFlags.Qualified)
                {
                    attrs += "qualified ";
                }
                par.Name(@head, attrs + @head.Name, "header");
                break;

            case ElaNodeType.ImportedVariable:
                var @imp = (ElaImportedVariable)exp;
                par.Name(@imp, (@imp.Private ? "private " : String.Empty) + @imp.LocalName + " = " + @imp.Name, "import");
                break;

            case ElaNodeType.Juxtaposition:
                var @juxta          = (ElaJuxtaposition)exp;
                var juxtaNode       = par.Simple(@juxta, "juxtaposition");
                var juxtaTargetNode = juxtaNode.Simple(@juxta.Target, "target");
                PopulateNodes(juxtaTargetNode, @juxta.Target);
                var juxtaParsNode = juxtaNode.Simple(@juxta, "positioned");
                foreach (var jp in @juxta.Parameters)
                {
                    PopulateNodes(juxtaParsNode, jp);
                }
                break;

            case ElaNodeType.Lambda:
                var @lam       = (ElaLambda)exp;
                var lamNode    = par.Simple(@lam, "lambda");
                var lamParNode = lamNode.Simple(@lam.Left, "left");
                PopulateNodes(lamParNode, @lam.Left);
                var lamRightNode = lamNode.Simple(@lam.Right, "right");
                PopulateNodes(lamRightNode, @lam.Right);
                break;

            case ElaNodeType.LazyLiteral:
                var @laz    = (ElaLazyLiteral)exp;
                var lazNode = par.Simple(@laz, "lazy");
                PopulateNodes(lazNode, @laz.Expression);
                break;

            case ElaNodeType.LetBinding:
                var @let    = (ElaLetBinding)exp;
                var letNode = par.Simple(@let, "let");

                if (@let.Expression != null)
                {
                    var letExprNode = letNode.Simple(@let.Expression, "expression");
                    PopulateNodes(letExprNode, @let.Expression);
                }

                var letEqNode = letNode.Simple(@let.Equations, "equations");
                PopulateNodes(letEqNode, @let.Equations);
                break;

            case ElaNodeType.ListLiteral:
                var @list    = (ElaListLiteral)exp;
                var listNode = par.Simple(@list, "list");
                foreach (var le in @list.Values)
                {
                    PopulateNodes(listNode, le);
                }
                break;

            case ElaNodeType.Match:
                var @mt        = (ElaMatch)exp;
                var mtNode     = par.Simple(@mt, "match");
                var mtExprNode = mtNode.Simple(@mt.Expression, "expression");
                PopulateNodes(mtExprNode, @mt.Expression);
                var mtEntriesNode = mtNode.Simple(@mt.Entries, "entries");
                PopulateNodes(mtEntriesNode, @mt.Entries);
                break;

            case ElaNodeType.ModuleInclude:
                var @inc    = (ElaModuleInclude)exp;
                var incNode = par.Simple(@inc, "include " + (String.IsNullOrEmpty(@inc.Alias) ? @inc.Name : @inc.Name + "@" + @inc.Alias) +
                                         (String.IsNullOrEmpty(@inc.DllName) ? String.Empty : "#" + @inc.DllName));
                foreach (var incNm in @inc.ImportList)
                {
                    PopulateNodes(incNode, incNm);
                }
                break;

            case ElaNodeType.NameReference:
                var @nam = (ElaNameReference)exp;
                par.Name(@nam, (@nam.Bang ? "!" : String.Empty) + @nam.Name);
                break;

            case ElaNodeType.Newtype:
                var @newt = (ElaNewtype)exp;
                while (@newt != null)
                {
                    var newtNode = par.Simple(@newt, (@newt.Extends ? "data " : (@newt.Opened ? "opentype " : "type ")) +
                                              (@newt.Prefix != null ? @newt.Prefix + "." : String.Empty) + @newt.Name);
                    foreach (var newtCons in @newt.Constructors)
                    {
                        PopulateNodes(newtNode, newtCons);
                    }
                    @newt = @newt.And;
                }
                break;

            case ElaNodeType.Placeholder:
                par.Name(exp, "_");
                break;

            case ElaNodeType.Primitive:
                var @prim = (ElaPrimitive)exp;
                par.Literal(@prim, @prim.Value.LiteralType, @prim.Value.ToString());
                break;

            case ElaNodeType.Range:
                var @rng         = (ElaRange)exp;
                var rngNode      = par.Simple(@rng, "range");
                var rngFirstNode = rngNode.Simple(@rng.First, "start");
                PopulateNodes(rngFirstNode, @rng.First);
                if (@rng.Second != null)
                {
                    var rngSecondNode = rngNode.Simple(@rng.Second, "step");
                    PopulateNodes(rngSecondNode, @rng.Second);
                }
                if (@rng.Last != null)
                {
                    var rngLastNode = rngNode.Simple(@rng.Last, "end");
                    PopulateNodes(rngLastNode, @rng.Last);
                }
                break;

            case ElaNodeType.RecordLiteral:
                var @rec    = (ElaRecordLiteral)exp;
                var recNode = par.Simple(@rec, "record");
                foreach (var recFld in @rec.Fields)
                {
                    PopulateNodes(recNode, recFld);
                }
                break;

            case ElaNodeType.Try:
                var @try        = (ElaTry)exp;
                var tryNode     = par.Simple(@try, "try");
                var tryExprNode = tryNode.Simple(@try.Expression, "expression");
                PopulateNodes(tryExprNode, @try.Expression);
                var tryEntriesNode = tryNode.Simple(@try.Entries, "entries");
                PopulateNodes(tryEntriesNode, @try.Entries);
                break;

            case ElaNodeType.TupleLiteral:
                var @tup    = (ElaTupleLiteral)exp;
                var tupNode = par.Simple(@tup, "tuple");
                foreach (var tupEl in @tup.Parameters)
                {
                    PopulateNodes(tupNode, tupEl);
                }
                break;

            case ElaNodeType.TypeCheck:
                var @typc    = (ElaTypeCheck)exp;
                var typcNode = par.Simple(@typc, "type check");
                var traits   = typcNode.Simple(@typc, "traits");
                foreach (var typcTra in @typc.Traits)
                {
                    typcNode.Name(@typc, (typcTra.Prefix != null ? typcTra.Prefix + "." : String.Empty) + typcTra.Name, "trait");
                }
                var typcExprNode = typcNode.Simple(@typc, "expression");
                PopulateNodes(typcExprNode, @typc.Expression);
                break;

            case ElaNodeType.TypeClass:
                var @class = (ElaTypeClass)exp;
                while (@class != null)
                {
                    var classNode = par.Simple(@class, "class " + @class.Name);
                    foreach (var classMem in @class.Members)
                    {
                        PopulateNodes(classNode, classMem);
                    }
                    @class = @class.And;
                }
                break;

            case ElaNodeType.UnitLiteral:
                par.Literal(exp, ElaTypeCode.Unit, "()");
                break;
            }
        }
Ejemplo n.º 21
0
        //Performs validation of overlapping for simple case of pattern matching
        //(such as 'match' expression with a single pattern per entry).
        private void ValidateOverlapSimple(LabelMap map, IEnumerable <ElaEquation> seq, ElaExpression mexp)
        {
            var lst = new List <ElaExpression>();

            foreach (var e in seq)
            {
                foreach (var o in lst)
                {
                    if (!e.Left.CanFollow(o))
                    {
                        AddWarning(map, ElaCompilerWarning.MatchEntryNotReachable, e.Left, FormatNode(e.Left), FormatNode(o));
                    }
                }

                lst.Add(e.Left);
            }
        }
Ejemplo n.º 22
0
 private void AddHint(ElaCompilerHint hint, ElaExpression exp, params object[] args)
 {
     AddHint(hint, exp.Line, exp.Column, args);
 }
Ejemplo n.º 23
0
        private ExprData CompileExpression(ElaExpression exp, LabelMap map, Hints hints, ElaExpression parent)
        {
            var exprData = ExprData.Empty;

            switch (exp.Type)
            {
            case ElaNodeType.DebugPoint:
                var dp = (ElaDebugPoint)exp;

                if (debug)
                {
                    if (dp.Action == ElaDebugAction.TracePoint)
                    {
                        var str = dp.Data ?? String.Empty;
                        cw.Emit(Op.Trace, AddString(str));
                    }

                    AddLinePragma(exp);
                }

                if (dp.Expression != null)
                {
                    return(CompileExpression(dp.Expression, map, hints, parent));
                }
                else
                {
                    cw.Emit(Op.Pushunit);
                }
                break;

            case ElaNodeType.DoNotation:
                CompileDoNotation((ElaDoNotation)exp, map, hints);
                break;

            case ElaNodeType.As:
            case ElaNodeType.Equation:
                AddError(ElaCompilerError.InvalidExpression, exp, FormatNode(exp));
                break;

            case ElaNodeType.Context:
            {
                var v = (ElaContext)exp;

                if (!v.Context.Parens && v.Context.Type == ElaNodeType.NameReference)
                {
                    var nr = (ElaNameReference)v.Context;

                    if (nr.Uppercase)
                    {
                        EmitSpecName(null, "$$" + nr.Name, nr, ElaCompilerError.UndefinedType);
                    }
                    else
                    {
                        CompileExpression(v.Context, map, Hints.None, v);
                        cw.Emit(Op.Api, 5);         //TypeCode
                    }
                }
                else if (!v.Context.Parens && v.Context.Type == ElaNodeType.FieldReference)
                {
                    var fr = (ElaFieldReference)v.Context;

                    if (Char.IsUpper(fr.FieldName[0]) && fr.TargetObject.Type == ElaNodeType.NameReference)
                    {
                        EmitSpecName(fr.TargetObject.GetName(), "$$" + fr.FieldName, fr, ElaCompilerError.UndefinedType);
                    }
                    else
                    {
                        CompileExpression(v.Context, map, Hints.None, v);
                        cw.Emit(Op.Api, 5);         //TypeCode
                    }
                }
                else
                {
                    CompileExpression(v.Context, map, Hints.None, v);
                    cw.Emit(Op.Force);
                    cw.Emit(Op.Api, 5);         //TypeCode
                }

                AddLinePragma(v);

                //This is only a possibility when '::: Expr' is a top level expression. In such a case it sets
                //a default context for the current call scope.
                if (v.Expression == null)
                {
                    cw.Emit(Op.Ctx);

                    if ((hints & Hints.Left) != Hints.Left)
                    {
                        cw.Emit(Op.Pushunit);
                    }
                }
                else
                {
                    var a = AddVariable();
                    cw.Emit(Op.Dup);
                    cw.Emit(Op.Ctx);
                    PopVar(a);
                    var newMap = map.Clone(a);
                    CompileExpression(v.Expression, newMap, hints, v);
                }
            }
            break;

            case ElaNodeType.Builtin:
            {
                var v = (ElaBuiltin)exp;
                CompileBuiltin(v.Kind, v, map, map.BindingName);

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, exp);
                }
            }
            break;

            case ElaNodeType.Generator:
            {
                CompileGenerator((ElaGenerator)exp, map, hints);

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, exp);
                }
            }
            break;

            case ElaNodeType.TypeCheck:
            {
                var n = (ElaTypeCheck)exp;
                CompileTypeCheck(n, map, hints);
            }
            break;

            case ElaNodeType.Range:
            {
                var r = (ElaRange)exp;
                CompileRange(exp, r, map, hints);

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, r);
                }
            }
            break;

            case ElaNodeType.LazyLiteral:
            {
                var v = (ElaLazyLiteral)exp;
                CompileLazy(v, map, hints);
            }
            break;

            case ElaNodeType.LetBinding:
            {
                var v = (ElaLetBinding)exp;
                StartScope(false, v.Line, v.Column);
                CompileEquationSet(v.Equations, map);
                CompileExpression(v.Expression, map, hints, v);
                EndScope();
            }
            break;

            case ElaNodeType.Try:
            {
                var s = (ElaTry)exp;
                CompileTryExpression(s, map, hints);
                AddWarning(map, ElaCompilerWarning.TryDeprecated, exp);
            }
            break;

            case ElaNodeType.Comprehension:
            {
                var c = (ElaComprehension)exp;
                AddLinePragma(c);

                if (c.Lazy)
                {
                    CompileLazyList(c.Generator, map, hints);
                }
                else
                {
                    cw.Emit(Op.Newlist);
                    CompileGenerator(c.Generator, map, Hints.None);
                    AddLinePragma(c);
                    cw.Emit(Op.Genfin);
                }

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, c);
                }
            }
            break;

            case ElaNodeType.Match:
            {
                var n = (ElaMatch)exp;
                CompileMatchExpression(n, map, hints);
            }
            break;

            case ElaNodeType.Lambda:
            {
                var f  = (ElaLambda)exp;
                var pc = CompileLambda(f);
                exprData = new ExprData(DataKind.FunParams, pc);

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, exp);
                }
            }
            break;

            case ElaNodeType.Condition:
            {
                var s = (ElaCondition)exp;
                CompileConditionalOperator(s, map, hints);
            }
            break;

            case ElaNodeType.Primitive:
            {
                var p = (ElaPrimitive)exp;
                exprData = CompilePrimitive(p, map, hints);
            }
            break;

            case ElaNodeType.RecordLiteral:
            {
                var p = (ElaRecordLiteral)exp;
                exprData = CompileRecord(p, map, hints);
            }
            break;

            case ElaNodeType.FieldReference:
            {
                var p  = (ElaFieldReference)exp;
                var sv = default(ScopeVar);

                //Here we check if a field reference is actually an external name
                //prefixed by a module alias. This call is not neccessary (modules
                //are first class) but is used as optimization.
                if (!TryOptimizeFieldReference(p, out sv))
                {
                    CompileExpression(p.TargetObject, map, Hints.None, p);
                    cw.Emit(Op.Pushstr, AddString(p.FieldName));
                    AddLinePragma(p);
                    cw.Emit(Op.Pushfld);
                }
                else if ((sv.Flags & ElaVariableFlags.Polyadric) == ElaVariableFlags.Polyadric)
                {
                    if (map.HasContext)
                    {
                        PushVar(map.Context.Value);
                    }
                    else
                    {
                        cw.Emit(Op.Pushunit);
                    }

                    cw.Emit(Op.Disp);
                }

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, exp);
                }
            }
            break;

            case ElaNodeType.ListLiteral:
            {
                var p = (ElaListLiteral)exp;
                exprData = CompileList(p, map, hints);
            }
            break;

            case ElaNodeType.NameReference:
            {
                var v = (ElaNameReference)exp;
                AddLinePragma(v);
                var scopeVar = GetVariable(v.Name, v.Line, v.Column);

                //Bang patterns are only allowed in functions and constructors
                if (v.Bang)
                {
                    AddError(ElaCompilerError.BangPatternNotValid, exp, FormatNode(exp));
                    AddHint(ElaCompilerHint.BangsOnlyFunctions, exp);
                }

                //This a polymorphic constant
                if ((scopeVar.Flags & ElaVariableFlags.Polyadric) == ElaVariableFlags.Polyadric)
                {
                    PushVar(scopeVar);

                    if (map.HasContext)
                    {
                        PushVar(map.Context.Value);
                    }
                    else
                    {
                        cw.Emit(Op.Pushunit);
                    }

                    cw.Emit(Op.Disp);
                }
                else if ((scopeVar.Flags & ElaVariableFlags.Context) == ElaVariableFlags.Context)
                {
                    //This is context value, not a real variable
                    cw.Emit(Op.Pushunit);
                    cw.Emit(Op.Api, (Int32)Api.CurrentContext);
                }
                else
                {
                    PushVar(scopeVar);
                }

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, v);
                }

                //Add some hints if we know how this name is initialized
                if ((scopeVar.VariableFlags & ElaVariableFlags.Function) == ElaVariableFlags.Function)
                {
                    exprData = new ExprData(DataKind.FunParams, scopeVar.Data);
                }
                else if ((scopeVar.VariableFlags & ElaVariableFlags.ObjectLiteral) == ElaVariableFlags.ObjectLiteral)
                {
                    exprData = new ExprData(DataKind.VarType, (Int32)ElaVariableFlags.ObjectLiteral);
                }
                else if ((scopeVar.VariableFlags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin)
                {
                    exprData = new ExprData(DataKind.Builtin, scopeVar.Data);
                }
            }
            break;

            case ElaNodeType.Placeholder:
            {
                if ((hints & Hints.Left) != Hints.Left)
                {
                    AddError(ElaCompilerError.PlaceholderNotValid, exp);
                }
                else
                {
                    AddLinePragma(exp);
                    cw.Emit(Op.Pop);
                }
            }
            break;

            case ElaNodeType.Juxtaposition:
            {
                var v = (ElaJuxtaposition)exp;
                exprData = CompileFunctionCall(v, map, hints);

                if ((hints & Hints.Left) == Hints.Left)
                {
                    AddValueNotUsed(map, v);
                }
            }
            break;

            case ElaNodeType.UnitLiteral:
                if ((hints & Hints.Left) != Hints.Left)
                {
                    cw.Emit(Op.Pushunit);
                }

                exprData = new ExprData(DataKind.VarType, (Int32)ElaTypeCode.Unit);
                break;

            case ElaNodeType.TupleLiteral:
            {
                var v = (ElaTupleLiteral)exp;
                exprData = CompileTuple(v, map, hints);
            }
            break;
            }

            return(exprData);
        }
Ejemplo n.º 24
0
 public static TreeNode Simple(this TreeNode par, ElaExpression exp, string str)
 {
     return(Element(par, exp, "", str, "Arrow", "{0}{1}"));
 }
Ejemplo n.º 25
0
 private void AddWarning(LabelMap map, ElaCompilerWarning warning, ElaExpression exp, params object[] args)
 {
     AddWarning(map, warning, exp.Line, exp.Column, args);
 }
Ejemplo n.º 26
0
        //This method can be called directly when a built-in is inlined.
        private void CompileBuiltinInline(ElaBuiltinKind kind, ElaExpression exp, LabelMap map, Hints hints)
        {
            switch (kind)
            {
            case ElaBuiltinKind.Fail:
                cw.Emit(Op.Throw);
                break;

            case ElaBuiltinKind.Seq:
                cw.Emit(Op.Force);
                cw.Emit(Op.Pop);
                break;

            case ElaBuiltinKind.ForwardPipe:
                cw.Emit(Op.Swap);
                cw.Emit(Op.Call);
                break;

            case ElaBuiltinKind.BackwardPipe:
                cw.Emit(Op.Call);
                break;

            case ElaBuiltinKind.LogicalOr:
            {
                var left  = AddVariable();
                var right = AddVariable();
                PopVar(left);
                PopVar(right);

                PushVar(left);
                var termLab = cw.DefineLabel();
                var exitLab = cw.DefineLabel();
                cw.Emit(Op.Brtrue, termLab);

                PushVar(right);
                cw.Emit(Op.Br, exitLab);
                cw.MarkLabel(termLab);
                cw.Emit(Op.PushI1_1);
                cw.MarkLabel(exitLab);
                cw.Emit(Op.Nop);
            }
            break;

            case ElaBuiltinKind.LogicalAnd:
            {
                var left  = AddVariable();
                var right = AddVariable();
                PopVar(left);
                PopVar(right);

                PushVar(left);
                var termLab = cw.DefineLabel();
                var exitLab = cw.DefineLabel();
                cw.Emit(Op.Brfalse, termLab);

                PushVar(right);
                cw.Emit(Op.Br, exitLab);
                cw.MarkLabel(termLab);
                cw.Emit(Op.PushI1_0);
                cw.MarkLabel(exitLab);
                cw.Emit(Op.Nop);
            }
            break;

            case ElaBuiltinKind.Head:
                cw.Emit(Op.Head);
                break;

            case ElaBuiltinKind.Tail:
                cw.Emit(Op.Tail);
                break;

            case ElaBuiltinKind.IsNil:
                cw.Emit(Op.Isnil);
                break;

            case ElaBuiltinKind.Negate:
                cw.Emit(Op.Neg);
                break;

            case ElaBuiltinKind.Length:
                cw.Emit(Op.Len);
                break;

            case ElaBuiltinKind.Force:
                cw.Emit(Op.Force);
                break;

            case ElaBuiltinKind.Not:
                cw.Emit(Op.Not);
                break;

            case ElaBuiltinKind.Show:
                cw.Emit(Op.Show);
                break;

            case ElaBuiltinKind.Concat:
                cw.Emit(Op.Concat);
                break;

            case ElaBuiltinKind.Add:
                cw.Emit(Op.Add);
                break;

            case ElaBuiltinKind.Divide:
                cw.Emit(Op.Div);
                break;

            case ElaBuiltinKind.Quot:
                cw.Emit(Op.Quot);
                break;

            case ElaBuiltinKind.Multiply:
                cw.Emit(Op.Mul);
                break;

            case ElaBuiltinKind.Power:
                cw.Emit(Op.Pow);
                break;

            case ElaBuiltinKind.Remainder:
                cw.Emit(Op.Rem);
                break;

            case ElaBuiltinKind.Modulus:
                cw.Emit(Op.Mod);
                break;

            case ElaBuiltinKind.Subtract:
                cw.Emit(Op.Sub);
                break;

            case ElaBuiltinKind.ShiftRight:
                cw.Emit(Op.Shr);
                break;

            case ElaBuiltinKind.ShiftLeft:
                cw.Emit(Op.Shl);
                break;

            case ElaBuiltinKind.Greater:
                cw.Emit(Op.Cgt);
                break;

            case ElaBuiltinKind.Lesser:
                cw.Emit(Op.Clt);
                break;

            case ElaBuiltinKind.Equal:
                cw.Emit(Op.Ceq);
                break;

            case ElaBuiltinKind.NotEqual:
                cw.Emit(Op.Cneq);
                break;

            case ElaBuiltinKind.GreaterEqual:
                cw.Emit(Op.Cgteq);
                break;

            case ElaBuiltinKind.LesserEqual:
                cw.Emit(Op.Clteq);
                break;

            case ElaBuiltinKind.BitwiseAnd:
                cw.Emit(Op.AndBw);
                break;

            case ElaBuiltinKind.BitwiseOr:
                cw.Emit(Op.OrBw);
                break;

            case ElaBuiltinKind.BitwiseXor:
                cw.Emit(Op.Xor);
                break;

            case ElaBuiltinKind.Cons:
                cw.Emit(Op.Cons);
                break;

            case ElaBuiltinKind.BitwiseNot:
                cw.Emit(Op.NotBw);
                break;

            case ElaBuiltinKind.GetValue:
                cw.Emit(Op.Pushelem);
                break;

            case ElaBuiltinKind.GetValueR:
                cw.Emit(Op.Swap);
                cw.Emit(Op.Pushelem);
                break;

            case ElaBuiltinKind.GetField:
                cw.Emit(Op.Pushfld);
                break;

            case ElaBuiltinKind.HasField:
                cw.Emit(Op.Hasfld);
                break;

            /* Api */
            case ElaBuiltinKind.Api1:
                cw.Emit(Op.Api, 1);
                break;

            case ElaBuiltinKind.Api2:
                cw.Emit(Op.Api, 2);
                break;

            case ElaBuiltinKind.Api3:
                cw.Emit(Op.Api, 3);
                break;

            case ElaBuiltinKind.Api4:
                cw.Emit(Op.Api, 4);
                break;

            case ElaBuiltinKind.Api5:
                cw.Emit(Op.Api, 5);
                break;

            case ElaBuiltinKind.Api6:
                cw.Emit(Op.Api, 6);
                break;

            case ElaBuiltinKind.Api7:
                cw.Emit(Op.Api, 7);
                break;

            case ElaBuiltinKind.Api8:
                cw.Emit(Op.Api, 8);
                break;

            case ElaBuiltinKind.Api9:
                cw.Emit(Op.Api, 9);
                break;

            case ElaBuiltinKind.Api10:
                cw.Emit(Op.Api, 10);
                break;

            case ElaBuiltinKind.Api11:
                cw.Emit(Op.Api, 11);
                break;

            case ElaBuiltinKind.Api12:
                cw.Emit(Op.Api, 12);
                break;

            case ElaBuiltinKind.Api13:
                cw.Emit(Op.Api, 13);
                break;

            case ElaBuiltinKind.Api14:
                cw.Emit(Op.Api, 14);
                break;

            case ElaBuiltinKind.Api15:
                cw.Emit(Op.Api, 15);
                break;

            case ElaBuiltinKind.Api16:
                cw.Emit(Op.Api, 16);
                break;

            case ElaBuiltinKind.Api17:
                cw.Emit(Op.Api, 17);
                break;

            case ElaBuiltinKind.Api18:
                cw.Emit(Op.Api, 18);
                break;

            case ElaBuiltinKind.Api101:
                cw.Emit(Op.Api2, 101);
                break;

            case ElaBuiltinKind.Api102:
                cw.Emit(Op.Api2, 102);
                break;

            case ElaBuiltinKind.Api103:
                cw.Emit(Op.Api2, 103);
                break;

            case ElaBuiltinKind.Api104:
                cw.Emit(Op.Api2, 104);
                break;

            case ElaBuiltinKind.Api105:
                cw.Emit(Op.Api2, 105);
                break;

            case ElaBuiltinKind.Api106:
                cw.Emit(Op.Api2, 106);
                break;

            case ElaBuiltinKind.Api107:
                cw.Emit(Op.Api2, 107);
                break;
            }
        }
Ejemplo n.º 27
0
 //This method generate a warning and hint and when a value is not used and
 //pops this value from the top of the stack.
 private void AddValueNotUsed(LabelMap map, ElaExpression exp)
 {
     AddWarning(map, ElaCompilerWarning.ValueNotUsed, exp, FormatNode(exp));
     AddHint(ElaCompilerHint.UseIgnoreToPop, exp, FormatNode(exp, true));
     cw.Emit(Op.Pop);
 }
Ejemplo n.º 28
0
        private void FindName(string name, CodeDocument doc, ElaExpression expr, List <SymbolLocation> syms)
        {
            if (expr == null)
            {
                return;
            }

            switch (expr.Type)
            {
            case ElaNodeType.DebugPoint:
                FindName(name, doc, ((ElaDebugPoint)expr).Expression, syms);
                break;

            case ElaNodeType.As:
            {
                var a = (ElaAs)expr;

                if (a.Name == name)
                {
                    syms.Add(new SymbolLocation(doc, a.Line, a.Column));
                }

                if (a.Expression != null)
                {
                    FindName(name, doc, a.Expression, syms);
                }
            }
            break;

            case ElaNodeType.EquationSet:
            {
                var b = (ElaEquationSet)expr;

                foreach (var e in b.Equations)
                {
                    FindName(name, doc, e, syms);
                }
            }
            break;

            case ElaNodeType.Builtin:
                break;

            case ElaNodeType.Newtype:
            {
                var b = (ElaNewtype)expr;

                foreach (var e in b.Constructors)
                {
                    FindName(name, doc, e, syms);
                }
            }
            break;

            case ElaNodeType.TypeClass:
            {
                var b = (ElaTypeClass)expr;

                if (b.Members != null)
                {
                    foreach (var m in b.Members)
                    {
                        FindName(name, doc, m, syms);
                    }
                }

                if (b.And != null)
                {
                    FindName(name, doc, b.And, syms);
                }
            }
            break;

            case ElaNodeType.ClassMember:
            {
                var b = (ElaClassMember)expr;

                if (b.Name == name)
                {
                    syms.Add(new SymbolLocation(doc, b.Line, b.Column));
                }
            }
            break;

            case ElaNodeType.ClassInstance:
            {
                var b = (ElaClassInstance)expr;

                if (b.Where != null)
                {
                    FindName(name, doc, b.Where, syms);
                }

                if (b.And != null)
                {
                    FindName(name, doc, b.And, syms);
                }
            }
            break;

            case ElaNodeType.Equation:
            {
                var b = (ElaEquation)expr;

                if (b.Left != null)
                {
                    FindName(name, doc, b.Left, syms);
                }

                if (b.Right != null)
                {
                    FindName(name, doc, b.Right, syms);
                }

                if (b.Next != null)
                {
                    FindName(name, doc, b.Next, syms);
                }
            }
            break;

            case ElaNodeType.LetBinding:
            {
                var b = (ElaLetBinding)expr;

                if (b.Equations != null)
                {
                    FindName(name, doc, b.Equations, syms);
                }

                if (b.Expression != null)
                {
                    FindName(name, doc, b.Expression, syms);
                }
            }
            break;

            case ElaNodeType.Comprehension:
            {
                var c = (ElaComprehension)expr;

                if (c.Generator != null)
                {
                    FindName(name, doc, c.Generator, syms);
                }
            }
            break;

            case ElaNodeType.Condition:
            {
                var c = (ElaCondition)expr;

                if (c.Condition != null)
                {
                    FindName(name, doc, c.Condition, syms);
                }

                if (c.True != null)
                {
                    FindName(name, doc, c.True, syms);
                }

                if (c.False != null)
                {
                    FindName(name, doc, c.False, syms);
                }
            }
            break;

            case ElaNodeType.Placeholder:
                break;

            case ElaNodeType.FieldDeclaration:
            {
                var f = (ElaFieldDeclaration)expr;

                if (f.FieldValue != null)
                {
                    FindName(name, doc, f.FieldValue, syms);
                }
            }
            break;

            case ElaNodeType.FieldReference:
            {
                var r = (ElaFieldReference)expr;

                if (r.TargetObject != null)
                {
                    FindName(name, doc, r.TargetObject, syms);
                }
            }
            break;

            case ElaNodeType.Juxtaposition:
            {
                var c = (ElaJuxtaposition)expr;
                FindName(name, doc, c.Target, syms);

                foreach (var p in c.Parameters)
                {
                    FindName(name, doc, p, syms);
                }
            }
            break;

            case ElaNodeType.Lambda:
            {
                var f = (ElaLambda)expr;

                if (f.Left != null)
                {
                    FindName(name, doc, f.Left, syms);
                }

                if (f.Right != null)
                {
                    FindName(name, doc, f.Right, syms);
                }
            }
            break;

            case ElaNodeType.Generator:
            {
                var g = (ElaGenerator)expr;

                if (g.Target != null)
                {
                    FindName(name, doc, g.Target, syms);
                }

                if (g.Pattern != null)
                {
                    FindName(name, doc, g.Pattern, syms);
                }

                if (g.Guard != null)
                {
                    FindName(name, doc, g.Guard, syms);
                }

                if (g.Body != null)
                {
                    FindName(name, doc, g.Body, syms);
                }
            }
            break;

            case ElaNodeType.ImportedVariable:
            {
                var v = (ElaImportedVariable)expr;

                if (v.LocalName == name || v.Name == name)
                {
                    syms.Add(new SymbolLocation(doc, v.Line, v.Column));
                }
            }
            break;

            case ElaNodeType.TypeCheck:
            {
                var i = (ElaTypeCheck)expr;

                if (i.Expression != null)
                {
                    FindName(name, doc, i.Expression, syms);
                }
            }
            break;

            case ElaNodeType.LazyLiteral:
            {
                var l = (ElaLazyLiteral)expr;

                if (l.Expression != null)
                {
                    FindName(name, doc, l.Expression, syms);
                }
            }
            break;

            case ElaNodeType.ListLiteral:
            {
                var l = (ElaListLiteral)expr;

                if (l.Values != null)
                {
                    foreach (var v in l.Values)
                    {
                        FindName(name, doc, v, syms);
                    }
                }
            }
            break;

            case ElaNodeType.Match:
            {
                var m = (ElaMatch)expr;

                if (m.Expression != null)
                {
                    FindName(name, doc, m.Expression, syms);
                }

                if (m.Entries != null)
                {
                    FindName(name, doc, m.Entries, syms);
                }
            }
            break;

            case ElaNodeType.ModuleInclude:
            {
                var m = (ElaModuleInclude)expr;

                if (m.Alias == name)
                {
                    syms.Add(new SymbolLocation(doc, m.Line, m.Column));
                }

                if (m.HasImportList)
                {
                    foreach (var i in m.ImportList)
                    {
                        FindName(name, doc, i, syms);
                    }
                }
            }
            break;

            case ElaNodeType.Primitive:
                break;

            case ElaNodeType.Range:
            {
                var r = (ElaRange)expr;

                if (r.First != null)
                {
                    FindName(name, doc, r.First, syms);
                }

                if (r.Second != null)
                {
                    FindName(name, doc, r.Second, syms);
                }

                if (r.Last != null)
                {
                    FindName(name, doc, r.Last, syms);
                }
            }
            break;

            case ElaNodeType.RecordLiteral:
            {
                var r = (ElaRecordLiteral)expr;

                if (r.Fields != null)
                {
                    foreach (var f in r.Fields)
                    {
                        FindName(name, doc, f, syms);
                    }
                }
            }
            break;

            case ElaNodeType.Try:
            {
                var t = (ElaTry)expr;

                if (t.Expression != null)
                {
                    FindName(name, doc, t.Expression, syms);
                }

                if (t.Entries != null)
                {
                    FindName(name, doc, t.Entries, syms);
                }
            }
            break;

            case ElaNodeType.TupleLiteral:
            {
                var t = (ElaTupleLiteral)expr;

                if (t.Parameters != null)
                {
                    foreach (var p in t.Parameters)
                    {
                        FindName(name, doc, p, syms);
                    }
                }
            }
            break;

            case ElaNodeType.NameReference:
            {
                var r = (ElaNameReference)expr;

                if (r.Name == name)
                {
                    syms.Add(new SymbolLocation(doc, r.Line, r.Column));
                }
            }
            break;
            }
        }
Ejemplo n.º 29
0
        //Pushes a primitive value. It can be a string, a char,
        //a 32-bit integer, a 64-bit integer, a 32-bit float, a 64-bit float,
        //a boolean or unit.
        private void PushPrimitive(ElaExpression exp, ElaLiteralValue val)
        {
            switch (val.LiteralType)
            {
            case ElaTypeCode.String:
                var str = val.AsString();

                //String is added to the string table and indexed
                //An empty string is pushed using special op typeId.
                if (str.Length == 0)
                {
                    cw.Emit(Op.Pushstr_0);
                }
                else
                {
                    cw.Emit(Op.Pushstr, AddString(str));
                }
                break;

            case ElaTypeCode.Char:
                cw.Emit(Op.PushCh, val.AsInteger());
                break;

            case ElaTypeCode.Integer:
                var v = val.AsInteger();

                if (v == 0)
                {
                    cw.Emit(Op.PushI4_0);
                }
                else
                {
                    cw.Emit(Op.PushI4, v);
                }
                break;

            case ElaTypeCode.Long:
                //64-bit long is pushed as two 32-bit integers
                cw.Emit(Op.PushI4, val.GetData().I4_1);
                cw.Emit(Op.PushI4, val.GetData().I4_2);
                cw.Emit(Op.NewI8);
                break;

            case ElaTypeCode.Single:
                cw.Emit(Op.PushR4, val.GetData().I4_1);
                break;

            case ElaTypeCode.Double:
                //64-bit float is pushed as two 32-bit integers
                cw.Emit(Op.PushI4, val.GetData().I4_1);
                cw.Emit(Op.PushI4, val.GetData().I4_2);
                cw.Emit(Op.NewR8);
                break;

            case ElaTypeCode.Boolean:
                cw.Emit(val.AsBoolean() ? Op.PushI1_1 : Op.PushI1_0);
                break;

            case ElaTypeCode.__Reserved:
                cw.Emit(Op.Pushstr, AddString(val.AsString()));
                var sv = GetVariable("literal'" + Char.ToLower(val.Postfix), exp.Line, exp.Column);
                PushVar(sv);
                cw.Emit(Op.Call);
                break;

            default:
                cw.Emit(Op.Pushunit);
                break;
            }
        }
Ejemplo n.º 30
0
 public static TreeNode Control(this TreeNode par, ElaExpression exp, string title, object data)
 {
     return(Element(par, exp, title, data, "Function", "{0} {1}"));
 }