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)); }
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); }