Ejemplo n.º 1
0
        private void AssignmentPreprocessor(AST.Node lhs)
        {
            if (!(lhs is AST.Identifier))
            {
                return; // only need to handle simple assignments
            }
            if (!this.isfunction)
            {
                return;
            }
            AST.Identifier target = (AST.Identifier)lhs;

            if (target.Type != AST.IdentifierType.UnQualifiedName)
            {
                return;
            }

            if (target.IsEnclosed)
            {
                if (this.variables.LocalAssignment.ContainsKey(target.Name))
                {
                    // Found the variable already used in a local assignment
                    target.IsEnclosed = false;
                    this.variables.LocalAssignment[target.Name].Add(target);
                }
                else
                {
                    if (!this.variables.GlobalAssignment.ContainsKey(target.Name))
                    {
                        // variable did not exists currently as global assignment
                        this.variables.GlobalAssignment[target.Name] = new List <AST.Identifier>();
                    }
                    // add the target as a global assignment target
                    this.variables.GlobalAssignment[target.Name].Add(target);
                }
            }
            else
            {
                if (!this.variables.LocalAssignment.ContainsKey(target.Name))
                {
                    this.variables.LocalAssignment[target.Name] = new List <AST.Identifier>();
                }

                if (this.variables.GlobalAssignment.ContainsKey(target.Name))
                {
                    // found the same variable as a global assignment target
                    //  move it to the local assignments
                    foreach (AST.Identifier item in this.variables.GlobalAssignment[target.Name])
                    {
                        item.IsEnclosed = false;
                        this.variables.LocalAssignment[target.Name].Add(item);
                    }

                    // remove from the global assignments' list
                    this.variables.GlobalAssignment.Remove(target.Name);
                }

                this.variables.LocalAssignment[target.Name].Add(target);
            }
        }
Ejemplo n.º 2
0
        public void BuildFunctionsAndVariables(AST.Node root)
        {
            var variableUsages = new Dictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> >();

            this.BuildVariableUsages(root, null, variableUsages);
            this.TraverseTree(root, variableUsages);
        }
Ejemplo n.º 3
0
        public override AST.Node ToAST(Env env)
        {
            /// Check the switch statement.
            Switch sw = env.GetSwitch();

            if (sw == null)
            {
                throw new Error(Pos, "default statement not in switch statement");
            }

            /// The expression of a case should be constant integer expression.
            AST.ConstIntegerExpr c = expr.ToASTExpr(env) as AST.ConstIntegerExpr;
            if (c == null)
            {
                throw new Error(Pos, "the expression of a case should be constant integer expression");
            }

            /// No two of the case constant expressions shall have the same value.
            /// TODO: The conversion.
            foreach (var e in sw.cases)
            {
                if (c.value == e.Item2.value)
                {
                    throw new Error(Pos, string.Format("duplicate value {0} in case", c.value));
                }
            }

            string label = env.AllocCaseLabel();

            sw.cases.AddLast(new Tuple <string, ConstIntegerExpr>(label, c));

            AST.Node s = stmt.ToAST(env);

            return(new AST.Labeled(label, s));
        }
Ejemplo n.º 4
0
 public static void CopyDebugData(AST.Node nodeTo, AST.Node nodeFrom)
 {
     if (null != nodeTo && null != nodeFrom)
     {
         nodeTo.col     = nodeFrom.col;
         nodeTo.endCol  = nodeFrom.endCol;
         nodeTo.endLine = nodeFrom.endLine;
         nodeTo.line    = nodeFrom.line;
     }
 }
Ejemplo n.º 5
0
 public IReadOnlyDictionary <Function, ILabel> CreateIR(AST.Node node)
 {
     return(node
            .ChildrenRecursive()
            .OfType <AST.FunctionDeclaration>()
            .Where(fun => !fun.IsForeign)
            .ToDictionary(
                decl => decl.Function,
                decl => this.functionGenerator.GenerateBody(decl.Function, decl)));
 }
Ejemplo n.º 6
0
        private AST.Node BuildDyadic(AST.Token symbol, AST.Node lhs, AST.Node rhs)
        {
            AST.Node node;

            if (lhs is AST.BuiltInFunction)
            {
                /* This will allow the following construct:
                 *  ((-)) * 5
                 */
                node = BuildMonadic(((AST.BuiltInFunction)lhs).Function, BuildMonadic(symbol, rhs));
            }
            else if (lhs is AST.BuiltInOperator)
            {
                /* This will allow the following construct:
                 *  ((-each)) * 5
                 */

                AST.Operator op = ((AST.BuiltInOperator)lhs).Operator;
                op.RightArgument = BuildMonadic(symbol, rhs);

                node = op;
            }
            else
            {
                switch (symbol.Type)
                {
                case Tokens.DO:
                    node = AST.Node.DyadicDo(lhs, rhs);
                    break;

                case Tokens.RESULT:     // Tokens.Assign
                    AssignmentPreprocessor(lhs);
                    node = AST.Node.Assign(lhs, rhs);
                    break;

                default:
                    if (rhs is AST.ExpressionList)
                    {
                        throw new ParseException("Incorrect call format", false);
                    }

                    node = AST.Node.DyadicFunction(symbol, lhs, rhs);
                    break;
                }
            }

            return(node);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Updates the given <see cref="AST.UserDefInvoke"/> node with the given <paramref name="argument"/> information.
        /// </summary>
        /// <param name="function">The <see cref="AST.UserDefInvoke"/> to update.</param>
        /// <param name="argument">The argument(s) to use for the node update.</param>
        /// <returns>The updated <see cref="AST.UserDefInvoke"/> node.</returns>
        private AST.UserDefInvoke UpdateUserDefInvoke(AST.UserDefInvoke function, AST.Node argument)
        {
            if (argument is AST.ExpressionList)
            {
                AST.ExpressionList arguments = (AST.ExpressionList)argument;
                foreach (AST.Node node in arguments.Items)
                {
                    function.Arguments.AddLast(node);
                }
            }
            else
            {
                function.Arguments.AddLast(argument);
            }

            return(function);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Retrieves the string format of the identifier list from left to right, leaving out any symbols after the last identifier.
        /// Given: A.B()
        ///     Return: "A.B"
        /// Given: A.B.C()[0]
        ///     Return: "A.B.C"
        /// Given: A.B().C
        ///     Return: "A.B"
        /// Given: A.B[0].C
        ///     Return: "A.B[0].C"
        /// </summary>
        /// <param name="identList"></param>
        /// <returns></returns>
        public static string GetIdentifierStringUntilFirstParenthesis(AST.Node node)
        {
            dynamic identList = node as IdentifierListNode;

            if (identList == null)
            {
                identList = node as AST.ImperativeAST.IdentifierListNode;
            }
            Validity.Assert(null != identList);
            string identListString = identList.ToString();
            int    removeIndex     = identListString.IndexOf('(');

            if (removeIndex > 0)
            {
                identListString = identListString.Remove(removeIndex);
            }
            return(identListString);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// A selection statement is a block whose scope is a strict subset
        /// of the scope of its enclosing block.
        ///
        /// The controlling expression of an if statement shall have scalar type.
        /// </summary>
        /// <param name="env"></param>
        /// <returns></returns>
        public override AST.Node ToAST(Env env)
        {
            env.PushBlockScope();
            AST.Expr e = expr.ToASTExpr(env);
            if (!e.Type.IsScalar)
            {
                throw new ETypeError(Pos, string.Format("expecting scalar type, given {0}", e.Type));
            }

            AST.Node t = then.ToAST(env);
            AST.Node o = other != null?other.ToAST(env) : null;

            env.PopScope();

            var labels = env.AllocIfLabel();

            return(new AST.If(e, t, o, labels.Item1, labels.Item2));
        }
Ejemplo n.º 10
0
        private AST.Node BuildMonadic(AST.Token symbol, AST.Node argument)
        {
            AST.Node node;

            if (symbol.Type == Tokens.DO)
            {
                node = AST.Node.MonadicDo(argument);
            }
            else if (argument is AST.ExpressionList)
            {
                node = AST.Node.BuiltinInvoke(symbol, (AST.ExpressionList)argument);
            }
            else
            {
                node = AST.Node.MonadicFunction(symbol, argument);
            }

            return(node);
        }
Ejemplo n.º 11
0
        private void BuildVariableUsages(
            AST.Node node,
            AST.FunctionDeclaration parent,
            IDictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> > result)
        {
            var newParent = parent;

            switch (node)
            {
            case AST.FunctionDeclaration declaration:
            {
                newParent = declaration;
                break;
            }

            case AST.VariableDeclaration declaration:
            {
                if (!result.ContainsKey(declaration))
                {
                    result.Add(declaration, new HashSet <AST.FunctionDeclaration>());
                }

                result[declaration].Add(parent);
                break;
            }

            case AST.Variable variable:
            {
                if (!result.ContainsKey(variable.Declaration))
                {
                    result.Add(variable.Declaration, new HashSet <AST.FunctionDeclaration>());
                }

                result[variable.Declaration].Add(parent);
                break;
            }
            }

            foreach (var child in node.Children())
            {
                this.BuildVariableUsages(child, newParent, result);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Builds the final AST for the specified SPPF node reference
        /// </summary>
        /// <param name="reference">A reference to an SPPF node in a specific version</param>
        /// <returns>The AST node for the SPPF reference</returns>
        public AST.Node BuildFinalAST(SPPFNodeRef reference)
        {
            SPPFNode        sppfNode = sppf.GetNode(reference.NodeId);
            SPPFNodeVersion version  = (sppfNode as SPPFNodeNormal).GetVersion(reference.Version);

            if (version.ChildrenCount == 0)
            {
                return(new AST.Node(version.Label));
            }

            AST.Node[] buffer = new AST.Node[version.ChildrenCount];
            for (int i = 0; i != version.ChildrenCount; i++)
            {
                buffer[i] = BuildFinalAST(version.Children[i]);
            }
            int first = result.Store(buffer, 0, version.ChildrenCount);

            return(new AST.Node(version.Label, version.ChildrenCount, first));
        }
Ejemplo n.º 13
0
 int GetDIFile(AST.Node node)
 {
     if (!debugInfoFileLookup.TryGetValue(node.token.filename, out int fileIdx))
     {
         var    fn  = Backend.EscapeString(System.IO.Path.GetFileName(node.token.filename));
         var    dir = Backend.EscapeString(System.IO.Path.GetDirectoryName(node.token.filename));
         string checksum;
         using (var md5 = System.Security.Cryptography.MD5.Create())
         {
             using (var stream = File.OpenRead(node.token.filename))
             {
                 checksum = ByteArrayToString(md5.ComputeHash(stream));
             }
         }
         var nodeString = $"!DIFile(filename: \"{fn}\", directory: \"{dir}\", checksumkind: CSK_MD5, checksum: \"{checksum}\")";
         fileIdx = AddDebugInfoNode(nodeString);
         debugInfoFileLookup.Add(node.token.filename, fileIdx);
     }
     return(fileIdx);
 }
Ejemplo n.º 14
0
        public override AST.Node ToAST(Env env)
        {
            /// The controlling expression shall have integer type.
            e = expr.ToASTExpr(env);
            if (!e.Type.IsInteger && e.Type.Kind != TKind.ENUM)
            {
                throw new ETypeError(Pos, "the controlling expression of switch statement shall have integer type");
            }

            /// Integer promotions are performed on the controlling expression.
            e = e.IntPromote();

            env.PushSwitch(this);

            /// Semantic check the statment.
            AST.Node s = stmt.ToAST(env);

            env.PopBreakable();

            return(new AST.Switch(breakLabel, cases, defaultLabel, e, s));
        }
Ejemplo n.º 15
0
        int GetDIScope(AST.Node scopeRoot)
        {
            int scopeIdx = -1;

            if (scopeRoot != null && !debugInfoScopeLookup.TryGetValue(scopeRoot, out scopeIdx))
            {
                switch (scopeRoot)
                {
                case AST.ProgramRoot programRoot:
                    scopeIdx = GetDICompileUnit(programRoot);
                    break;

                case AST.FunctionDefinition fun:
                    scopeIdx = GetDISubprogram(fun);
                    break;

                case AST.Block block:
                    if (block.parent is AST.FunctionDefinition fd)
                    {
                        scopeIdx = GetDISubprogram(fd);
                    }
                    else
                    {
                        scopeIdx = GetDILexicalBlock(block);
                    }
                    break;

                case AST.Module ns:
                    // TODO(pragma): NAMESPACES
                    scopeIdx = GetDIScope(debugRootNode);
                    break;

                default:
                    scopeIdx = -1;
                    break;
                }
            }
            return(scopeIdx);
        }
Ejemplo n.º 16
0
        private void TraverseTree(
            AST.Node node,
            IReadOnlyDictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> > variableUsages,
            Function parentFunction = null)
        {
            switch (node)
            {
            case AST.FunctionDeclaration functionDeclaration:
            {
                var function = FunctionBuilder.CreateFunction(functionDeclaration, parentFunction);
                functionDeclaration.Function = function;
                foreach (var argument in functionDeclaration.Parameters)
                {
                    argument.IntermediateVariable = this.ReserveLocation(function, variableUsages, argument);
                }

                if (functionDeclaration.Body != null)
                {
                    this.TraverseTree(functionDeclaration.Body, variableUsages, function);
                }

                return;
            }

            case AST.VariableDeclaration variableDeclaration:
            {
                variableDeclaration.IntermediateVariable = this.ReserveLocation(parentFunction, variableUsages, variableDeclaration);
                break;
            }
            }

            foreach (var child in node.Children())
            {
                this.TraverseTree(child, variableUsages, parentFunction);
            }
        }
Ejemplo n.º 17
0
        public override AST.Node ToAST(Env env)
        {
            /// Check the switch statement.
            Switch sw = env.GetSwitch();

            if (sw == null)
            {
                throw new Error(Pos, "default statement not in switch statement");
            }

            /// At most one default statement in a switch.
            if (sw.defaultLabel != null)
            {
                throw new Error(Pos, "at most one default label in a switch statement");
            }

            string label = env.AllocDefaultLabel();

            sw.defaultLabel = label;

            AST.Node s = stmt.ToAST(env);

            return(new AST.Labeled(label, s));
        }
Ejemplo n.º 18
0
 /// <summary>
 /// Sets the content of the i-th item
 /// </summary>
 /// <param name="index">The index of the item to set</param>
 /// <param name="symbol">The symbol</param>
 /// <param name="action">The tree action</param>
 public void SetAt(int index, TableElemRef symbol, TreeAction action)
 {
     nodes[index]   = new AST.Node(symbol);
     actions[index] = action;
 }
Ejemplo n.º 19
0
 private void SetupUserDefFunction()
 {
     this.isfunction = true;
     this.function   = null;
     this.variables  = new Variables();
 }
Ejemplo n.º 20
0
 private void TearDownUserDefFunction()
 {
     this.isfunction = false;
     this.function   = null;
     this.variables  = null;
 }
 public ScanObj(int t, AST.Node val, LexLocation loc)
 {
     this.token = t; this.yylval = val; this.yylloc = loc;
 }
Ejemplo n.º 22
0
 private void SetupUserDefFunction()
 {
     this.isfunction = true;
     this.function = null;
     this.variables = new Variables();
 }
Ejemplo n.º 23
0
 private void TearDownUserDefFunction()
 {
     this.isfunction = false;
     this.function = null;
     this.variables = null;
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Initializes paren expression.
 /// </summary>
 internal ParenExpr(AST.Node expr)
 {
     Debug.Assert(expr != null, "expr != null");
     _expr = expr;
 }
Ejemplo n.º 25
0
 /// <summary>
 /// Initializes paren expression.
 /// </summary>
 internal ParenExpr(AST.Node expr)
 {
     Debug.Assert(expr != null, "expr != null");
     _expr = expr;
 }
Ejemplo n.º 26
0
 public UserFunctionResolver(List <string> parameters, AST.Node function, SymbolTable table)
 {
     this.call     = function;
     this.symTable = table;
     paramList     = parameters;
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Finalizes the parse tree and returns it
 /// </summary>
 /// <param name="root">The identifier of the SPPF node that serves as root</param>
 /// <returns>The final parse tree</returns>
 public AST GetTree(int root)
 {
     AST.Node astRoot = BuildFinalAST(new SPPFNodeRef(root, 0));
     result.StoreRoot(astRoot);
     return(result);
 }
 virtual public void visit(AST.Node node)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Initializes the root of this sub-tree
 /// </summary>
 /// <param name="symbol">The root's symbol</param>
 /// <param name="action">The tree action applied on the root</param>
 public void SetupRoot(TableElemRef symbol, TreeAction action)
 {
     nodes[0]   = new AST.Node(symbol);
     actions[0] = action;
 }
Ejemplo n.º 30
0
        public static MonkeyObject Eval(AST.Node node, Object.Environment environment)
        {
            MonkeyObject left;
            MonkeyObject index;
            MonkeyObject val;

            switch (node)
            {
            case AST.Program p:
                return(evalProgram(p, environment));

            case AST.BlockStatement bs:
                return(evalBlockStatement(bs, environment));

            case AST.ExpressionStatement xs:
                return(Eval(xs.Expression, environment));

            case AST.LetStatement ls:
                val = Eval(ls.Value, environment);
                if (val?.Type == MonkeyObjectType.ERROR)
                {
                    return(val);
                }

                environment.Set(ls.Name.Value, val);
                break;

            case AST.ReturnStatement rs:
                val = Eval(rs.ReturnValue, environment);
                if (val?.Type == MonkeyObjectType.ERROR)
                {
                    return(val);
                }

                return(new MonkeyReturnValue {
                    Value = val
                });

            case AST.HashLiteral hl:
                return(evalHashLiteral(hl, environment));

            case AST.ArrayLiteral al:
                var elements = evalExpressions(al.Elements, environment);
                if (elements.Count == 1 && elements[0]?.Type == MonkeyObjectType.ERROR)
                {
                    return(elements[0]);
                }
                return(new MonkeyArray {
                    Elements = elements
                });

            case AST.FunctionLiteral fl:
                return(new Object.Function {
                    Parameters = fl.Parameters, Env = environment, Body = fl.Body
                });

            case AST.IfExpression ifx:
                return(evalIfExpression(ifx, environment));

            case AST.CallExpression cl:
                var function = Eval(cl.Function, environment);
                if (function?.Type == MonkeyObjectType.ERROR)
                {
                    return(function);
                }

                var args = evalExpressions(cl.Arguments, environment);
                if (args.Count == 1 && args[0]?.Type == MonkeyObjectType.ERROR)
                {
                    return(args[0]);
                }

                return(applyFunction(function, args));

            case AST.InfixExpression ix:
                left = Eval(ix.Left, environment);
                if (left?.Type == MonkeyObjectType.ERROR)
                {
                    return(left);
                }

                index = Eval(ix.Right, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }

                return(evalInfixExpression(ix.Op, left, index));

            case AST.PrefixExpression px:
                index = Eval(px.Right, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }

                return(evalPrefixExpression(px.Op, index));

            case AST.IndexExpression idx:
                left = Eval(idx.Left, environment);
                if (left?.Type == MonkeyObjectType.ERROR)
                {
                    return(left);
                }

                index = Eval(idx.Index, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }
                return(evalIndexExpression(left, index));

            case AST.IntegerLiteral il:
                return(new MonkeyInteger {
                    Value = il.Value
                });

            case AST.BooleanExpression b:
                return(nativeBoolToMonkeyBoolean(b.Value));

            case AST.Identifier id:
                return(evalIdentifier(id, environment));

            case AST.StringLiteral sl:
                return(new MonkeyString {
                    Value = sl.Value
                });
            }

            return(null);
        }