Ejemplo n.º 1
0
        public Maybe <ILineNode> HandleDirective(EAParser p, Token directive, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            string directiveName = directive.Content.Substring(1);

            if (directives.TryGetValue(directiveName, out IDirective? toExec))
            {
                if (!toExec.RequireInclusion || p.IsIncluding)
                {
                    if (toExec.MinParams <= parameters.Count && (!toExec.MaxParams.HasValue || parameters.Count <= toExec.MaxParams))
                    {
                        return(toExec.Execute(p, directive, parameters, tokens));
                    }
                    else
                    {
                        p.Error(directive.Location, "Invalid number of parameters (" + parameters.Count + ") to directive " + directiveName + ".");
                    }
                }
            }
            else
            {
                p.Error(directive.Location, "Directive not recognized: " + directiveName);
            }

            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 2
0
        public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            Maybe <string> existantFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), parameters[0].ToString());

            if (!existantFile.IsNothing)
            {
                try
                {
                    string pathname = existantFile.FromJust;

                    FileStream inputFile        = new FileStream(pathname, FileMode.Open);
                    Tokenizer  newFileTokenizer = new Tokenizer();
                    tokens.PrependEnumerator(newFileTokenizer.Tokenize(inputFile).GetEnumerator());
                }
                catch (Exception)
                {
                    p.Error(self.Location, "Error reading file \"" + parameters[0].ToString() + "\".");
                }
            }
            else
            {
                p.Error(parameters[0].MyLocation, "Could not find file \"" + parameters[0].ToString() + "\".");
            }
            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 3
0
        private static Maybe <IList <Token> > TokenizeParam(EAParser p, IParamNode param)
        {
            switch (param.Type)
            {
            case ParamType.STRING:
                Token     input = ((StringNode)param).MyToken;
                Tokenizer t     = new Tokenizer();
                return(new Just <IList <Token> >(new List <Token>(t.TokenizeLine(input.Content, input.FileName, input.LineNumber, input.ColumnNumber))));

            case ParamType.MACRO:
                try
                {
                    IList <Token> myBody = new List <Token>(((MacroInvocationNode)param).ExpandMacro());
                    return(new Just <IList <Token> >(myBody));
                }
                catch (KeyNotFoundException)
                {
                    MacroInvocationNode asMacro = (MacroInvocationNode)param;
                    p.Error(asMacro.MyLocation, "Undefined macro: " + asMacro.Name);
                }
                break;

            case ParamType.LIST:
                ListNode n = (ListNode)param;
                return(new Just <IList <Token> >(new List <Token>(n.ToTokens())));

            case ParamType.ATOM:
                return(new Just <IList <Token> >(new List <Token>(((IAtomNode)param).ToTokens())));
            }
            return(new Nothing <IList <Token> >());
        }
Ejemplo n.º 4
0
 public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
 {
     if (p.Inclusion.IsEmpty)
     {
         p.Error(self.Location, "No matching if[n]def.");
     }
     else
     {
         p.Inclusion = p.Inclusion.Tail;
     }
     return(new Nothing <ILineNode>());
 }
Ejemplo n.º 5
0
        public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            Maybe <string> existantFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), parameters[0].ToString() !);

            if (!existantFile.IsNothing)
            {
                try
                {
                    string pathname = existantFile.FromJust;
                    return(new Just <ILineNode>(new DataNode(p.CurrentOffset, File.ReadAllBytes(pathname))));
                }
                catch (Exception)
                {
                    p.Error(self.Location, "Error reading file \"" + parameters[0].ToString() + "\".");
                }
            }
            else
            {
                p.Error(parameters[0].MyLocation, "Could not find file \"" + parameters[0].ToString() + "\".");
            }
            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 6
0
        public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            bool           flag = true;
            Maybe <string> identifier;

            foreach (IParamNode parameter in parameters)
            {
                if (parameter.Type == ParamType.ATOM && !(identifier = ((IAtomNode)parameter).GetIdentifier()).IsNothing)
                {
                    flag &= p.Macros.ContainsName(identifier.FromJust) || p.Definitions.ContainsKey(identifier.FromJust); //TODO: Built in definitions?
                }
                else
                {
                    p.Error(parameter.MyLocation, "Definition name must be an identifier.");
                }
            }
            p.Inclusion = new ImmutableStack <bool>(flag, p.Inclusion);
            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 7
0
        public Maybe <ILineNode> Execute(EAParser parse, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_GENERIC);

            Maybe <string> validFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), IOUtility.GetToolFileName(parameters[0].ToString()));

            if (validFile.IsNothing)
            {
                parse.Error(parameters[0].MyLocation, "Tool " + parameters[0].ToString() + " not found.");
                return(new Nothing <ILineNode>());
            }

            //from http://stackoverflow.com/a/206347/1644720
            // Start the child process.
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.RedirectStandardError = true;
            // Redirect the output stream of the child process.
            p.StartInfo.WorkingDirectory       = Path.GetDirectoryName(self.FileName);
            p.StartInfo.UseShellExecute        = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.CreateNoWindow         = true;
            p.StartInfo.FileName = validFile.FromJust;
            StringBuilder argumentBuilder = new StringBuilder();

            for (int i = 1; i < parameters.Count; i++)
            {
                parameters[i].AsAtom().IfJust((IAtomNode n) => { parameters[i] = n.Simplify(); });
                argumentBuilder.Append(parameters[i].PrettyPrint());
                argumentBuilder.Append(' ');
            }
            argumentBuilder.Append("--to-stdout");
            p.StartInfo.Arguments = argumentBuilder.ToString();
            p.Start();
            // Do not wait for the child process to exit before
            // reading to the end of its redirected stream.
            // p.WaitForExit();
            // Read the output stream first and then wait.
            MemoryStream outputBytes = new MemoryStream();
            MemoryStream errorStream = new MemoryStream();

            p.StandardOutput.BaseStream.CopyTo(outputBytes);
            p.StandardError.BaseStream.CopyTo(errorStream);
            p.WaitForExit();

            byte[] output = outputBytes.GetBuffer().Take((int)outputBytes.Length).ToArray();
            if (errorStream.Length > 0)
            {
                parse.Error(self.Location, Encoding.ASCII.GetString(errorStream.GetBuffer().Take((int)errorStream.Length).ToArray()));
            }
            else if (output.Length >= 7 && Encoding.ASCII.GetString(output.Take(7).ToArray()) == "ERROR: ")
            {
                parse.Error(self.Location, Encoding.ASCII.GetString(output.Skip(7).ToArray()));
            }
            else
            {
                outputBytes.Position = 0; //Reset MemoryStream position so StreamReader starts reading from beginning.
                Tokenizer t = new Tokenizer();
                tokens.PrependEnumerator(t.Tokenize(outputBytes, Path.GetFileName(self.FileName) + ", Line " + self.LineNumber + "; " + parameters[0].ToString()).GetEnumerator());
            }

            ExecTimer.Timer.AddTimingPoint(parameters[0].ToString().ToLower());

            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 8
0
        public Maybe <ILineNode> Execute(EAParser parse, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_GENERIC);

            Maybe <string> validFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), IOUtility.GetToolFileName(parameters[0].ToString() !));

            if (validFile.IsNothing)
            {
                parse.Error(parameters[0].MyLocation, "Tool " + parameters[0].ToString() + " not found.");
                return(new Nothing <ILineNode>());
            }
            //TODO: abstract out all this running stuff into a method so I don't have code duplication with inctext

            //from http://stackoverflow.com/a/206347/1644720
            // Start the child process.
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.RedirectStandardError = true;
            // Redirect the output stream of the child process.
            p.StartInfo.WorkingDirectory       = Path.GetDirectoryName(self.FileName) !;
            p.StartInfo.UseShellExecute        = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.CreateNoWindow         = true;
            p.StartInfo.FileName = validFile.FromJust;
            StringBuilder argumentBuilder = new StringBuilder();

            for (int i = 1; i < parameters.Count; i++)
            {
                if (parameters[i].Type == ParamType.ATOM)
                {
                    parameters[i] = ((IAtomNode)parameters[i]).Simplify();
                }
                argumentBuilder.Append(parameters[i].PrettyPrint());
                argumentBuilder.Append(' ');
            }
            argumentBuilder.Append("--to-stdout");
            p.StartInfo.Arguments = argumentBuilder.ToString();
            p.Start();
            // Do not wait for the child process to exit before
            // reading to the end of its redirected stream.
            // p.WaitForExit();
            // Read the output stream first and then wait.
            MemoryStream outputBytes = new MemoryStream();
            MemoryStream errorStream = new MemoryStream();

            p.StandardOutput.BaseStream.CopyTo(outputBytes);
            p.StandardError.BaseStream.CopyTo(errorStream);
            p.WaitForExit();

            byte[] output = outputBytes.GetBuffer().Take((int)outputBytes.Length).ToArray();
            if (errorStream.Length > 0)
            {
                parse.Error(self.Location, Encoding.ASCII.GetString(errorStream.GetBuffer().Take((int)errorStream.Length).ToArray()));
            }
            else if (output.Length >= 7 && Encoding.ASCII.GetString(output.Take(7).ToArray()) == "ERROR: ")
            {
                parse.Error(self.Location, Encoding.ASCII.GetString(output.Skip(7).ToArray()));
            }

            ExecTimer.Timer.AddTimingPoint(parameters[0].ToString() !.ToLower());

            return(new Just <ILineNode>(new DataNode(parse.CurrentOffset, output)));
        }
Ejemplo n.º 9
0
        public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            if (parameters[0].Type == ParamType.MACRO)
            {
                MacroInvocationNode signature = (MacroInvocationNode)(parameters[0]);
                string        name            = signature.Name;
                IList <Token> myParams        = new List <Token>();
                foreach (IList <Token> l1 in signature.Parameters)
                {
                    if (l1.Count != 1 || l1[0].Type != TokenType.IDENTIFIER)
                    {
                        p.Error(l1[0].Location, "Macro parameters must be identifiers (got " + l1[0].Content + ").");
                    }
                    else
                    {
                        myParams.Add(l1[0]);
                    }
                }

                /* if (!p.IsValidMacroName(name, myParams.Count))
                 * {
                 *  if (p.IsReservedName(name))
                 *  {
                 *      p.Error(signature.MyLocation, "Invalid redefinition: " + name);
                 *  }
                 *  else
                 *      p.Warning(signature.MyLocation, "Redefining " + name + '.');
                 * }*/
                if (p.Macros.HasMacro(name, myParams.Count))
                {
                    p.Warning(signature.MyLocation, "Redefining " + name + '.');
                }
                Maybe <IList <Token> > toRepl;
                if (parameters.Count != 2)
                {
                    toRepl = new Just <IList <Token> >(new List <Token>());
                }
                else
                {
                    toRepl = ExpandParam(p, parameters[1], myParams.Select((Token t) => t.Content));
                }
                if (!toRepl.IsNothing)
                {
                    p.Macros.AddMacro(new Macro(myParams, toRepl.FromJust), name, myParams.Count);
                }
            }
            else
            {
                //Note [mutually] recursive definitions are handled by Parser expansion.
                Maybe <string> maybeIdentifier;
                if (parameters[0].Type == ParamType.ATOM && !(maybeIdentifier = ((IAtomNode)parameters[0]).GetIdentifier()).IsNothing)
                {
                    string name = maybeIdentifier.FromJust;
                    if (p.Definitions.ContainsKey(name))
                    {
                        p.Warning(parameters[0].MyLocation, "Redefining " + name + '.');
                    }
                    if (parameters.Count == 2)
                    {
                        Maybe <IList <Token> > toRepl = ExpandParam(p, parameters[1], Enumerable.Empty <string>());
                        if (!toRepl.IsNothing)
                        {
                            p.Definitions[name] = new Definition(toRepl.FromJust);
                        }
                    }
                    else
                    {
                        p.Definitions[name] = new Definition();
                    }
                }
                else
                {
                    p.Error(parameters[0].MyLocation, "Definition names must be identifiers (got " + parameters[0].ToString() + ").");
                }
            }
            return(new Nothing <ILineNode>());
        }
Ejemplo n.º 10
0
        public bool Interpret()
        {
            Tokenizer t = new Tokenizer();

            ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_GENERIC);

            foreach (Tuple <string, string> defpair in EAOptions.Instance.defs)
            {
                myParser.ParseAll(t.TokenizeLine("#define " + defpair.Item1 + " " + defpair.Item2, "cmd", 0));
            }

            IList <ILineNode> lines = new List <ILineNode>(myParser.ParseAll(t.Tokenize(sin, iFile)));

            /* First pass on AST: Identifier resolution.
             *
             * Suppose we had the code
             *
             * POIN myLabel
             * myLabel:
             *
             * At parse time, myLabel did not exist for the POIN.
             * It is at this point we want to make sure all references to identifiers are valid, before assembling.
             */
            List <Token> undefinedIds = new List <Token>();

            foreach (ILineNode line in lines)
            {
                try
                {
                    line.EvaluateExpressions(undefinedIds);
                } catch (MacroInvocationNode.MacroException e)
                {
                    myParser.Error(e.CausedError.MyLocation, "Unexpanded macro.");
                }
            }

            foreach (Token errCause in undefinedIds)
            {
                if (errCause.Content.StartsWith(Pool.pooledLabelPrefix, StringComparison.Ordinal))
                {
                    myParser.Error(errCause.Location, "Unpooled data (forgot #pool?)");
                }
                else
                {
                    myParser.Error(errCause.Location, "Undefined identifier: " + errCause.Content);
                }
            }

            /* Last step: assembly */

            ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_DATAWRITE);

            if (!log.HasErrored)
            {
                foreach (ILineNode line in lines)
                {
                    if (Program.Debug)
                    {
                        log.Message(Log.MsgKind.DEBUG, line.PrettyPrint(0));
                    }

                    line.WriteData(output);
                }

                output.Commit();

                log.Output.WriteLine("No errors. Please continue being awesome.");
                return(true);
            }
            else
            {
                log.Output.WriteLine("Errors occurred; no changes written.");
                return(false);
            }
        }