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