Example #1
0
 public void Clear()
 {
     Macros.Clear();
     Definitions.Clear();
     Raws.Clear();
     Inclusion     = ImmutableStack <bool> .Nil;
     CurrentOffset = 0;
     pastOffsets.Clear();
 }
Example #2
0
 public bool IsReservedName(string name)
 {
     return(Raws.ContainsKey(name.ToUpper()) || SpecialCodes.Contains(name.ToUpper()));
 }
Example #3
0
        private Maybe <ILineNode> ParseStatement(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            while (ExpandIdentifier(tokens, scopes))
            {
            }
            head = tokens.Current;
            tokens.MoveNext();
            //TODO: Replace with real raw information, and error if not valid.
            IList <IParamNode> parameters;

            //TODO: Make intelligent to reject malformed parameters.
            //TODO: Parse parameters after checking code validity.
            if (tokens.Current.Type != TokenType.NEWLINE && tokens.Current.Type != TokenType.SEMICOLON)
            {
                parameters = ParseParamList(tokens, scopes);
            }
            else
            {
                parameters = new List <IParamNode>();
                tokens.MoveNext();
            }

            string upperCodeIdentifier = head.Content.ToUpperInvariant();

            if (SpecialCodes.Contains(upperCodeIdentifier))
            {
                switch (upperCodeIdentifier)
                {
                case "ORG":
                    if (parameters.Count != 1)
                    {
                        Error(head.Location, "Incorrect number of parameters in ORG: " + parameters.Count);
                    }
                    else
                    {
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                (int temp) =>
                        {
                            if (temp > 0x2000000)
                            {
                                Error(parameters[0].MyLocation, "Tried to set offset to 0x" + temp.ToString("X"));
                            }
                            else
                            {
                                CurrentOffset = temp;
                            }
                        }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to ORG."); }
                            );
                    }
                    break;

                case "PUSH":
                    if (parameters.Count != 0)
                    {
                        Error(head.Location, "Incorrect number of parameters in PUSH: " + parameters.Count);
                    }
                    else
                    {
                        pastOffsets.Push(new Tuple <int, bool>(CurrentOffset, offsetInitialized));
                    }
                    break;

                case "POP":
                    if (parameters.Count != 0)
                    {
                        Error(head.Location, "Incorrect number of parameters in POP: " + parameters.Count);
                    }
                    else if (pastOffsets.Count == 0)
                    {
                        Error(head.Location, "POP without matching PUSH.");
                    }
                    else
                    {
                        Tuple <int, bool> tuple = pastOffsets.Pop();

                        CurrentOffset     = tuple.Item1;
                        offsetInitialized = tuple.Item2;
                    }
                    break;

                case "MESSAGE":
                    Message(head.Location, PrettyPrintParams(parameters));
                    break;

                case "WARNING":
                    Warning(head.Location, PrettyPrintParams(parameters));
                    break;

                case "ERROR":
                    Error(head.Location, PrettyPrintParams(parameters));
                    break;

                case "ASSERT":
                    if (parameters.Count != 1)
                    {
                        Error(head.Location, "Incorrect number of parameters in ASSERT: " + parameters.Count);
                    }
                    else
                    {
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) =>
                        {
                            atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                (int temp) =>
                            {
                                if (temp < 0)
                                {
                                    Error(parameters[0].MyLocation, "Assertion error: " + temp);
                                }
                            });
                        },
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to ASSERT."); }
                            );
                    }
                    break;

                case "PROTECT":
                    if (parameters.Count == 1)
                    {
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                (int temp) =>
                        {
                            protectedRegions.Add(new Tuple <int, int, Location>(temp, 4, head.Location));
                        }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); });
                    }
                    else if (parameters.Count == 2)
                    {
                        int  start = 0, end = 0;
                        bool errorOccurred = false;
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); errorOccurred = true; }).IfJust(
                                (int temp) =>
                        {
                            start = temp;
                        }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); errorOccurred = true; });
                        parameters[1].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); errorOccurred = true; }).IfJust(
                                (int temp) =>
                        {
                            end = temp;
                        }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); errorOccurred = true; });
                        if (!errorOccurred)
                        {
                            int length = end - start;
                            if (length > 0)
                            {
                                protectedRegions.Add(new Tuple <int, int, Location>(start, length, head.Location));
                            }
                            else
                            {
                                Warning(head.Location, "Protected region not valid (end offset not after start offset). No region protected.");
                            }
                        }
                    }
                    else
                    {
                        Error(head.Location, "Incorrect number of parameters in PROTECT: " + parameters.Count);
                    }
                    break;

                case "ALIGN":
                    if (parameters.Count != 1)
                    {
                        Error(head.Location, "Incorrect number of parameters in ALIGN: " + parameters.Count);
                    }
                    else
                    {
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                (int temp) =>
                        {
                            CurrentOffset = CurrentOffset % temp != 0 ? CurrentOffset + temp - CurrentOffset % temp : CurrentOffset;
                        }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to ALIGN"); }
                            );
                    }
                    break;

                case "FILL":
                    if (parameters.Count > 2 || parameters.Count == 0)
                    {
                        Error(head.Location, "Incorrect number of parameters in FILL: " + parameters.Count);
                    }
                    else
                    {
                        // FILL <amount> [value]

                        int amount = 0;
                        int value  = 0;

                        if (parameters.Count == 2)
                        {
                            // param 2 (if given) is fill value

                            parameters[1].AsAtom().IfJust(
                                (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                    (int val) => { value = val; }),
                                () => { Error(parameters[0].MyLocation, "Expected atomic param to FILL"); });
                        }

                        // param 1 is amount of bytes to fill
                        parameters[0].AsAtom().IfJust(
                            (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust(
                                (int val) => { amount = val; }),
                            () => { Error(parameters[0].MyLocation, "Expected atomic param to FILL"); });

                        var data = new byte[amount];

                        for (int i = 0; i < amount; ++i)
                        {
                            data[i] = (byte)value;
                        }

                        var node = new DataNode(CurrentOffset, data);

                        CheckDataWrite(amount);
                        CurrentOffset += amount;

                        return(new Just <ILineNode>(node));
                    }

                    break;
                }
                return(new Nothing <ILineNode>());
            }
            else if (Raws.ContainsKey(upperCodeIdentifier))
            {
                //TODO: Check for matches. Currently should type error.
                foreach (Raw r in Raws[upperCodeIdentifier])
                {
                    if (r.Fits(parameters))
                    {
                        if ((CurrentOffset % r.Alignment) != 0)
                        {
                            Error(head.Location, string.Format("Bad code alignment (offset: {0:X8})", CurrentOffset));
                        }
                        StatementNode temp = new RawNode(r, head, CurrentOffset, parameters);

                        CheckDataWrite(temp.Size);
                        CurrentOffset += temp.Size; //TODO: more efficient spacewise to just have contiguous writing and not an offset with every line?

                        return(new Just <ILineNode>(temp));
                    }
                }
                //TODO: Better error message (a la EA's ATOM ATOM [ATOM,ATOM])
                Error(head.Location, "Incorrect parameters in raw " + head.Content + '.');
                IgnoreRestOfStatement(tokens);
                return(new Nothing <ILineNode>());
            }
            else //TODO: Move outside of this else.
            {
                Error(head.Location, "Unrecognized code: " + head.Content);
                return(new Nothing <ILineNode>());
            }
        }
Example #4
0
 /// <summary>
 /// Releases any resources used by the index entry.
 /// </summary>
 public void Dispose()
 {
     Raws.Dispose();
     Strings.Clear();
     TagData = null;
 }