예제 #1
0
        private CanCauseError <Code> GetCode(byte[] code, int currOffset, IEnumerable <Priority> prioritiesToUse)
        {
            CanCauseError <ICodeTemplate> template = this.codeStorage.FindTemplate(code, currOffset, prioritiesToUse);

            if (template.CausedError)
            {
                return(template.ConvertError <Code> ());
            }
            ICodeTemplate            result      = template.Result;
            int                      lengthBytes = result.GetLengthBytes(code, currOffset);
            CanCauseError <string[]> assembly    = result.GetAssembly(code, currOffset);

            if (assembly.CausedError)
            {
                return(assembly.ConvertError <Code> ());
            }
            return((CanCauseError <Code>) new Code(assembly.Result, result, lengthBytes, currOffset));
        }
예제 #2
0
        private IEnumerable <KeyValuePair <INamed <string>, string[]> > FirstPass(IPositionableInputStream input,
                                                                                  Context assemblyContext, ILog log)
        {
            while (true)
            {
                string line = input.ReadLine();
                if (line == null)
                {
                    break;
                }

                string[] code = Nintenlord.Utility.Parser.SplitToParameters(line);

                if (code.Length > 0)
                {
                    if (code[0].EndsWith(":"))
                    {
                        code = HandleLabels(input, assemblyContext, log, code);
                    }

                    if (code.Length == 0)
                    {
                        continue;
                    }

                    IBuiltInCode builtIn;
                    if (buildInCodes.TryGetValue(code[0], out builtIn))
                    {
                        string error;
                        if (builtIn.Matches("Code " + code[0], code.Length - 1, out error))
                        {
                            var causedError = builtIn.FirstPass(code, assemblyContext);
                            if (causedError)
                            {
                                log.AddError(input.GetErrorString(causedError.ErrorMessage));
                            }
                            yield return(new KeyValuePair <INamed <string>, string[]>(builtIn, code));
                        }
                        else
                        {
                            log.AddError(input.GetErrorString(error));
                        }
                    }
                    else
                    {
                        ICodeTemplate template = codeStorage.FindTemplate(code);

                        if (template != null)
                        {
                            if (assemblyContext.Offset % template.OffsetMod != 0)
                            {
                                log.AddError(input.GetErrorString(
                                                 string.Format(
                                                     "Code {0}'s offset {1} is not divisible by {2}",
                                                     template.Name,
                                                     assemblyContext.Offset,
                                                     template.OffsetMod
                                                     )));
                            }
                            assemblyContext.Offset += template.GetLengthBytes(code);
                            yield return(new KeyValuePair <INamed <string>, string[]>(template, code));
                        }
                        else
                        {
                            log.AddError(input.GetErrorString(string.Format(
                                                                  "No code named {0} with {1} parameters found",
                                                                  code[0],
                                                                  code.Length - 1
                                                                  )));
                        }
                    }
                }
            }
        }
        private ScopeStructure <int> ExecuteLayoutPass <T>(IExpression <int> expression, ScopeStructure <int> scope, T output)
        {
            switch (expression.Type)
            {
            case EAExpressionType.Scope:
            {
                ScopeStructure <int> newScope = new ScopeStructure <int> (scope);
                scopeStructures [(Scope <int>)expression] = newScope;

                foreach (IExpression <int> child in expression.GetChildren())
                {
                    ExecuteLayoutPass(child, newScope, output);
                }

                break;
            }

            case EAExpressionType.Code:
            {
                Code <int> code = expression as Code <int>;

                if (code.IsEmpty || HandleBuiltInCodeLayout(code, scope))
                {
                    break;
                }

                if (code.CodeName.Name == "ASMC" && code.Parameters[0].ToString() != "" && !System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[0].ToString(), @"\A\b(0[xX])?[0-9a-fA-F]+\b\Z"))
                {
                    scope.RegisterASMCLabel(code.Parameters[0].ToString());
                }

                Types.Type[] sig = ((IEnumerable <IExpression <int> >)code.Parameters).Select(new Func <IExpression <int>, Types.Type> (Types.Type.GetType <int>)).ToArray();

                CanCauseError <ICodeTemplate> templateError = this.storer.FindTemplate(code.CodeName.Name, sig);

                if (templateError.CausedError)
                {
                    AddError <int, ICodeTemplate> ((IExpression <int>)code, templateError);
                    break;
                }

                ICodeTemplate template = templateError.Result;

                // Checking alignment
                if (currentOffset % template.OffsetMod != 0)
                {
                    this.AddError <int> ((IExpression <int>)code, "Code {0}'s offset {1} is not divisible by {2}", (object)code.CodeName.Name, (object)this.currentOffset.ToHexString("$"), (object)template.OffsetMod);
                }

                // TODO: maybe we want to store the template somewhere to lookup for later?
                // May or may not be faster than computing it again in the write pass

                this.currentOffset += template.GetLengthBytes(((IEnumerable <IExpression <int> >)code.Parameters).ToArray());
                break;
            }

            case EAExpressionType.Labeled:
            {
                // record label names
                scope.SetLocalLabelAddress(((LabelExpression <int>)expression).LabelName, currentOffset);

                CanCauseError err = scope.AddNewSymbol(((LabelExpression <int>)expression).LabelName, new ValueExpression <int> (this.currentOffset, new FilePosition()));

                if (err.CausedError)
                {
                    AddWarning(expression, err.ErrorMessage);
                }

                break;
            }

            case EAExpressionType.Assignment:
            {
                Assignment <int>    assingment = (Assignment <int>)expression;
                CanCauseError <int> value      = Folding.Fold(assingment.Value, x => this.GetSymbolValue(scope, x));

                CanCauseError err = null;

                if (value.CausedError)
                {
                    err = scope.AddNewSymbol(assingment.Name, assingment.Value);
                }
                else
                {
                    err = scope.AddNewSymbol(assingment.Name, new ValueExpression <int> (value.Result, new FilePosition()));
                }

                if (err.CausedError)
                {
                    AddWarning(expression, err.ErrorMessage);
                }

                break;
            }

            case EAExpressionType.RawData:
            {
                RawData <int> rawData = (RawData <int>)expression;
                this.currentOffset += rawData.Data.Length;

                break;
            }

            default:
                throw new ArgumentException("Badly formed tree.");
            }

            // DeclareExternASMCLabels<T>(scope, output);
            return(scope);
        }