private void HandleBuiltInProtect(Code <int> code, ScopeStructure <int> scope) { if (code.ParameterCount.IsInRange(1, 1)) { CanCauseError <int> canCauseError = Folding.Fold(code [0], (x => this.GetSymbolValue(scope, x))); if (!canCauseError.CausedError) { this.protectedRegions.Add(new Tuple <int, int> (canCauseError.Result, 4)); } } else if (code.ParameterCount.IsInRange(2, 2)) { CanCauseError <int> firstParam = Folding.Fold(code [0], (x => this.GetSymbolValue(scope, x))); CanCauseError <int> secondParam = Folding.Fold(code [1], (x => this.GetSymbolValue(scope, x))); if (!firstParam.CausedError && !secondParam.CausedError) { if (firstParam.Result < secondParam.Result) { this.protectedRegions.Add(new Tuple <int, int> (firstParam.Result, secondParam.Result - firstParam.Result)); } else { this.log.AddWarning("Protected region not valid (end offset not after start offset). No region protected."); } } } else { this.AddNotCorrectParameters <int> (code, 2); } }
private string ExpressionToString(IExpression <T> exp, AssemblyContext <T> assemblyContext) { switch (exp.Type) { case EAExpressionType.List: return(exp.GetChildren().ToElementWiseString(", ", "[", "]")); case EAExpressionType.Code: var code = (Code <T>)exp; return(code.CodeName.Name + code.Parameters.Select( x => ExpressionToString(x, assemblyContext)).ToElementWiseString(" ", " ", "")); case EAExpressionType.XOR: case EAExpressionType.AND: case EAExpressionType.OR: case EAExpressionType.LeftShift: case EAExpressionType.RightShift: case EAExpressionType.Division: case EAExpressionType.Multiply: case EAExpressionType.Modulus: case EAExpressionType.Minus: case EAExpressionType.Sum: case EAExpressionType.Value: case EAExpressionType.Symbol: return((from val in Folding.Fold(exp, y => GetSymbolVal(y, assemblyContext), intType) select intType.ToString(val, 16)).ValueOrDefault(exp.ToString)); //case EAExpressionType.Scope: //case EAExpressionType.Labeled: //case EAExpressionType.Assignment: default: throw new ArgumentException("malformed tree"); } }
private void OnFoldNeeded(int firstLine, int lastLine, ScNotification scn) { var end = LineCount; while (GetLineIndentation(firstLine) != 0 && firstLine > 0) { firstLine--; } while (GetLineIndentation(lastLine) != 0 && lastLine > end) { lastLine--; } if (firstLine < 0 || lastLine > end) { return; } var ev = new FoldNeededEventArgs(firstLine, lastLine); var h = FoldNeeded; if (h != null) { h(this, ev); Folding.Fold(ev.Regions); } }
private string ExpressionToString(IExpression <int> exp, ScopeStructure <int> scope) { switch (exp.Type) { case EAExpressionType.Code: Code <int> code = exp as Code <int>; return(code.CodeName.Name + ((IEnumerable <IExpression <int> >)code.Parameters).Select((x => this.ExpressionToString(x, scope))).ToElementWiseString <string> (" ", " ", "")); case EAExpressionType.XOR: case EAExpressionType.AND: case EAExpressionType.OR: case EAExpressionType.LeftShift: case EAExpressionType.RightShift: case EAExpressionType.ArithmeticRightShift: case EAExpressionType.Division: case EAExpressionType.Multiply: case EAExpressionType.Modulus: case EAExpressionType.Minus: case EAExpressionType.Sum: case EAExpressionType.Value: case EAExpressionType.Symbol: CanCauseError <int> canCauseError = Folding.Fold(exp, (y => this.GetSymbolValue(scope, y))); if (canCauseError.CausedError) { return(exp.ToString()); } return(canCauseError.Result.ToHexString("0x")); case EAExpressionType.List: return(exp.GetChildren().ToElementWiseString <IExpression <int> > (", ", "[", "]")); default: throw new ArgumentException("malformed tree"); } }
private void HandleBuiltInOffsetAlign(Code <int> code, ScopeStructure <int> scope) { if (code.ParameterCount.IsInRange(1, 1)) { if (code [0] is ExpressionList <int> ) { this.AddNotAtomTypeParameter <int> (code [0]); } else { CanCauseError <int> error = Folding.Fold(code [0], (x => this.GetSymbolValue(scope, x))); if (error.CausedError) { this.AddError <int, int> ((IExpression <int>)code, error); } else { this.currentOffset = this.currentOffset.ToMod(error.Result); } } } else { this.AddNotCorrectParameters <int> (code, 1); } }
private void HandleBuiltInAssert(Code <int> code, ScopeStructure <int> scope) { if (code.ParameterCount.IsInRange(1, 1)) { if (code [0] is ExpressionList <int> ) { this.AddNotAtomTypeParameter <int> (code [0]); } else { CanCauseError <int> error = Folding.Fold(code [0], (x => this.GetSymbolValue(scope, x))); if (error.CausedError) { this.AddError((IExpression <int>)code, error); } else if (error.Result < 0) { this.AddError(code, "Assertion failed."); } } } else { this.AddNotCorrectParameters <int> (code, 1); } }
private void PrintAssemblyCode(Code <int> code, ScopeStructure <int> scope, TextWriter output) { output.Write("\t"); for (int i = 0; i < code.Parameters.Length; i++) { // support EA macro in inline assembly if (!scope.IsLocalLabelExisted(code.Parameters[i].ToString()) && !scope.GetSymbolValue(code.Parameters[i].ToString()).CausedError) { output.Write(" #0x{0:X}", Folding.Fold(code.Parameters[i], (x => this.GetSymbolValue(scope, x))).Result); } else { output.Write(" {0}", code.Parameters[i].ToString()); } if (i == 0) { output.Write("\t"); if (code.Parameters[0].ToString() == "push" || code.Parameters[0].ToString() == "pop") { output.Write("{"); } } if (i != code.Parameters.Length - 1) { if (i != 0) { output.Write(","); } if (code.Parameters[0].ToString().StartsWith("ldr") || code.Parameters[0].ToString().StartsWith("str")) { if (i == 1) { output.Write("["); } } // Console.WriteLine(code.Parameters[i + 1].ToString()); if (System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[i + 1].ToString(), @"^\d+$")) { output.Write("#"); } } else { if (code.Parameters[0].ToString() == "push" || code.Parameters[0].ToString() == "pop") { output.Write(" }"); } else if (code.Parameters[0].ToString().StartsWith("ldr") || code.Parameters[0].ToString().StartsWith("str")) { output.Write(" ]"); } output.Write("\n"); } } }
private void HandleBuiltInOffsetChange(Code <int> code, ScopeStructure <int> scope) { if (code.ParameterCount.IsInRange(1, 1) && !(code [0] is ExpressionList <int>)) { CanCauseError <int> canCauseError = Folding.Fold(code [0], (x => this.GetSymbolValue(scope, x))); if (!canCauseError.CausedError) { this.currentOffset = canCauseError.Result; } } }
private CanCauseError <T> GetSymbolVal(string symbolName, AssemblyContext <T> assemblyContext) { if (symbolName.Equals(currentOffsetCode, stringComparison) || symbolName.Equals(offsetChanger, stringComparison)) { return(intType.FromInt(assemblyContext.CurrentOffset)); } else { return(from expression in assemblyContext.CurrentScope.GetSymbolValue(symbolName) from foldResult in Folding.Fold(expression, x => GetSymbolVal(x, assemblyContext), intType) select foldResult); } }
internal static CanCauseError <int[]> GetValues(IExpression <int> parameter, TemplateParameter paramTemp, Func <string, int?> getSymbolValue, IPointerMaker pointerMaker) { int[] numArray; if (parameter is ExpressionList <int> ) { ExpressionList <int> expressionList = parameter as ExpressionList <int>; numArray = new int[expressionList.ComponentCount]; for (int index = 0; index < expressionList.ComponentCount; ++index) { CanCauseError <int> canCauseError = Folding.Fold(expressionList[index], getSymbolValue); if (canCauseError.CausedError) { return(canCauseError.ConvertError <int[]>()); } numArray[index] = canCauseError.Result; } } else { CanCauseError <int> canCauseError = Folding.Fold(parameter, getSymbolValue); if (canCauseError.CausedError) { return(canCauseError.ConvertError <int[]>()); } if (paramTemp.pointer && pointerMaker != null) { numArray = new int[1] { pointerMaker.MakePointer(canCauseError.Result) } } ; else { numArray = new int[1] { canCauseError.Result } }; } return((CanCauseError <int[]>)numArray); }
protected override void EndAction() { #if TraceMouse Trace.WriteLine(string.Format("GraphSceneMouseFolding EndAction HitCount {0}", HitCount)); Trace.WriteLine(string.Format("GraphSceneMouseFolding EndAction Focused: {0}", Focused)); #endif if (HitCount == 1) { Folding.Fold(() => Folding.Folder.Toggle()); LastMouseTime = 0; HitCount = 0; Focused = null; } if (HitCount > 1) { Focused = null; HitCount = 0; } base.EndAction(); }
private int?GetSymbolValue(ScopeStructure <int> scope, string symbolName) { if (symbolName.Equals(currentOffsetCode, StringComparison.OrdinalIgnoreCase) || symbolName.Equals(offsetChanger, StringComparison.OrdinalIgnoreCase)) { return(new int?(this.currentOffset)); } CanCauseError <IExpression <int> > symbolValue = scope.GetSymbolValue(symbolName); if (symbolValue.CausedError) { return(new int?()); } CanCauseError <int> canCauseError = Folding.Fold(symbolValue.Result, (x => this.GetSymbolValue(scope, x))); if (canCauseError.CausedError) { return(new int?()); } return(new int?(canCauseError.Result)); }
private bool HandleBuiltInCode(Code <T> code, AssemblyContext <T> assemblyContext, bool addToLog) { string text; switch (code.CodeName.Name) { case messagePrinterCode: if (addToLog) { text = ExpressionToString(code, assemblyContext); assemblyContext.Log.AddMessage(text.Substring(code.CodeName.Name.Length + 1)); } return(true); case errorPrinterCode: if (addToLog) { text = ExpressionToString(code, assemblyContext); assemblyContext.Log.AddError(text.Substring(code.CodeName.Name.Length + 1)); } return(true); case warningPrinterCode: if (addToLog) { text = ExpressionToString(code, assemblyContext); assemblyContext.Log.AddWarning(text.Substring(code.CodeName.Name.Length + 1)); } return(true); case currentOffsetCode: case offsetAlinger: if (code.ParameterCount.IsInRange(1, 1)) { if (code[0] is ExpressionList <T> ) { if (addToLog) { assemblyContext.AddNotAtomTypeParameter(code[0]); } } else { var align = Folding.Fold(code[0], x => CanCauseError <T> .Error("No symbols available."), intType); if (align.CausedError) { if (addToLog) { assemblyContext.AddError(code, align); } } else { assemblyContext.CurrentOffset = assemblyContext.CurrentOffset.ToMod(intType.GetIntValue(align.Result)); } } } else { if (addToLog) { assemblyContext.AddNotCorrectParameters(code, 1); } } return(true); case offsetChanger: if (code.ParameterCount.IsInRange(1, 1)) { if (code[0] is ExpressionList <T> ) { if (addToLog) { assemblyContext.AddNotAtomTypeParameter(code[0]); } } else { var newOffset = Folding.Fold(code[0], x => CanCauseError <T> .Error("No symbols available."), intType); if (newOffset.CausedError) { if (addToLog) { assemblyContext.AddError(code, newOffset); } } else { assemblyContext.CurrentOffset = intType.GetIntValue(newOffset.Result); } } } else { if (addToLog) { assemblyContext.AddNotCorrectParameters(code, 1); } } return(true); default: return(false); } }
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 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); }