private void ExecuteWritePass(TextWriter output, IExpression <int> expression, ScopeStructure <int> scope) { // This is to be executed *after* the layout pass switch (expression.Type) { case EAExpressionType.Scope: { ScopeStructure <int> newScope = scopeStructures [(Scope <int>)expression]; foreach (IExpression <int> child in expression.GetChildren()) { ExecuteWritePass(output, child, newScope); } break; } case EAExpressionType.Code: { Code <int> code = expression as Code <int>; // alignment. ALIGN 2^n => .align n if (!code.IsEmpty && code.CodeName.Name == offsetAligner && code.ParameterCount.IsInRange(1, 1) && !(code.Parameters[0] is ExpressionList <int>)) { output.WriteLine("\t.align {0}", Math.Ceiling(Math.Log(Folding.Fold(code.Parameters[0], (x => this.GetSymbolValue(scope, x))).Result, 2))); } if (code.IsEmpty || HandleBuiltInCodeWrite(code, scope, output)) { break; } bool TFlag = false; // bool ExtFlag = false; if (code.CodeName.Name == "ASMC") { if (code.Parameters.Length > 0 && code.Parameters[0].ToString() != "" && !scope.IsLocalLabelExisted(code.Parameters[0].ToString()) && !System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[0].ToString(), @"\A\b(0[xX])?[0-9a-fA-F]+\b\Z")) { // ExtFlag = true; } else { TFlag = true; } } // Maybe all of this template lookup up can be made faster by // storing the found template from the layout pass? 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; } // We won't check for alignment as it should already have been done in the layout pass ICodeTemplate template = templateError.Result; /*if (template is CodeTemplate && code.Parameters.Length > 0) * { * for (int i = 0; i < code.Parameters.Length; i++) * { * if(scope.GetRegisteredASMCLabels().Exists(o => o == code.Parameters[i].ToString())) * { * (template as CodeTemplate).AddExternLabel(i, code.Parameters[i].ToString()); * } * } * }*/ CanCauseError <byte[]> data = template.GetData(code.Parameters, x => this.GetSymbolValue(scope, x), scope); Dictionary <int, string> localLabels = template.GetLocalLabels(); Dictionary <int, string> externLabels = template.GetExternLabels(); var labels = localLabels.Union(externLabels).ToList(); if (data.CausedError) { // Can't compute code data, so we err this.AddError <int, byte[]> (expression, data); } else { // Write data if (labels.Count == 0) { TryWrite(output, expression, currentOffset, data.Result); } else { int startIndex = 0; foreach (KeyValuePair <int, string> k in labels) { // Console.WriteLine("pos:" + k.Key + " label:" + k.Value); if (k.Key - startIndex > 0) { TryWrite(output, expression, currentOffset, data.Result.Skip(startIndex).Take(k.Key - startIndex).ToArray()); } startIndex = k.Key + 4; if (TFlag == true && scope.IsLocalLabelExisted(k.Value)) { output.WriteLine("\t.word {0}+1", k.Value); TFlag = false; } else { output.WriteLine("\t.word {0}", k.Value); } } if (data.Result.Length - startIndex > 4) { TryWrite(output, expression, currentOffset, data.Result.Skip(startIndex).Take(data.Result.Length - startIndex).ToArray()); } } } this.currentOffset += data.Result.Length; /*for (int i = 0; i < code.Parameters.Length; i++) * { * // Console.WriteLine(code.Parameters[i]); * if (scope.IsLabelExisted(code.Parameters[i].ToString())) * { * output.WriteLine("\t.word {0}", code.Parameters[i]); * this.currentOffset += 4; * } * else * { * IExpression<int>[] parameter = new IExpression<int>[] { code.Parameters[i] }; * CanCauseError<byte[]> data = template.GetDataUnit(parameter, x => this.GetSymbolValue(scope, x)); * if (data.CausedError) * // Can't compute code data, so we err * this.AddError<int, byte[]>(expression, data); * else * { * // Write data * TryWrite(output, expression, currentOffset, data.Result); * this.currentOffset += data.Result.Length; * } * } * }*/ break; } case EAExpressionType.RawData: { RawData <int> rawData = (RawData <int>)expression; TryWrite(output, expression, this.currentOffset, rawData.Data); this.currentOffset += rawData.Data.Length; break; } case EAExpressionType.Labeled: //TODO Add label attribute: ".global LabelName" output.WriteLine(((LabelExpression <int>)expression).LabelName + ":"); break; case EAExpressionType.Assignment: //TODO .set/.equ, but it doesn't matter break; default: throw new ArgumentException("Badly formed tree."); } }
private void ExecuteWritePass(BinaryWriter output, IExpression <int> expression, ScopeStructure <int> scope) { // This is to be executed *after* the layout pass switch (expression.Type) { case EAExpressionType.Scope: { ScopeStructure <int> newScope = scopeStructures [(Scope <int>)expression]; foreach (IExpression <int> child in expression.GetChildren()) { ExecuteWritePass(output, child, newScope); } break; } case EAExpressionType.Code: { Code <int> code = expression as Code <int>; if (code.IsEmpty || HandleBuiltInCodeWrite(code, scope)) { break; } // Maybe all of this template lookup up can be made faster by // storing the found template from the layout pass? 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; } // We won't check for alignment as it should already have been done in the layout pass ICodeTemplate template = templateError.Result; CanCauseError <byte[]> data = template.GetData(code.Parameters, x => this.GetSymbolValue(scope, x), scope); if (data.CausedError) { // Can't compute code data, so we err this.AddError <int, byte[]> (expression, data); } else { // Write data TryWrite(output, expression, currentOffset, data.Result); this.currentOffset += data.Result.Length; } break; } case EAExpressionType.RawData: { RawData <int> rawData = (RawData <int>)expression; TryWrite(output, expression, this.currentOffset, rawData.Data); this.currentOffset += rawData.Data.Length; break; } case EAExpressionType.Labeled: case EAExpressionType.Assignment: break; default: throw new ArgumentException("Badly formed tree."); } }