public FunctionDefinition(string name, Span span, string documentation, ConstDefinition signature, StructDefinition argumentStruct, StructDefinition returnStruct, Definition?parent = null) : base(name, span, documentation, parent) { Signature = signature; ArgumentStruct = argumentStruct; ReturnStruct = returnStruct; }
private static bool CompareType(StructDefinition defn, Type type) { var fields = type.GetFields(); if (defn.Members.Count != fields.Length) { return(false); } for (var i = 0; i < fields.Length; i++) { if (fields[i].Name != defn.Members[i].Name) { return(false); } if (fields[i].FieldType.IsArray) { var attrs = fields[i].GetCustomAttributes(typeof(SerializationAttribute), true); if (attrs.Length == 0) { throw new InvalidOperationException("Array fields must have a valid SerializationAttribute"); } var attr = attrs[0] as SerializationAttribute; if (attr.ArraySize != defn.Members[i].ArraySize) { return(false); } } } return(true); }
private void GenerateStructMetadata(StructDefinition definition) { foreach (KeyValuePair <string, DefineVariableNode> field in definition.ContainFields) { AnalyzeVarDef(field.Value, false); } }
private static void TraverseDefinitions(XElement node, List <StructDefinition> list, ref bool inside) { if (node.Name == "h4") { if (node.Value == "C Specification") { inside = true; } } else if (node.Name == "code") { if (inside) { XAttribute attrClass = node.Attribute("class"); if (attrClass != null && attrClass.Value == "language-c++") { string v = node.Value; var item = new StructDefinition() { raw = v, }; list.Add(item); inside = false; } } } foreach (XElement item in node.Elements()) { TraverseDefinitions(item, list, ref inside); } }
public override string GenerateCodeForStruct(StructDefinition structDef) { if (structDef.NameToken.Value == "Value") { // I need to do fancy stuff with unions, so special case this one. return(this.LoadTextResource("Resources/ValueStruct.txt", new Dictionary <string, string>())); } StringBuilder sb = new StringBuilder(); sb.Append("struct "); sb.Append(structDef.NameToken.Value); sb.Append(" {\n"); for (int i = 0; i < structDef.ArgNames.Length; ++i) { string fieldName = structDef.ArgNames[i].Value; PType fieldType = structDef.ArgTypes[i]; sb.Append('\t'); sb.Append(this.TranslateType(fieldType)); sb.Append(' '); sb.Append(fieldName); sb.Append(";\n"); } sb.Append("};\n\n"); return(sb.ToString()); }
public override void LeaveStructDefinition(StructDefinition node) { CantBeMarkedAbstract(node); CantBeMarkedFinal(node); CantBeMarkedStatic(node); CantBeMarkedPartial(node); }
public object Read(GR2Reader gr2, StructDefinition definition, MemberDefinition member, uint arraySize, object parent) { var controls = new List<UInt16>((int)arraySize); for (int i = 0; i < arraySize; i++) controls.Add(gr2.Reader.ReadUInt16()); return controls; }
public override AstNode Visit(StructDefinition node) { // Fix the vtable. try { node.GetStructure().FixInheritance(); } catch (ModuleException error) { Error(node, error.Message); } // Create default constructor. CreateDefaultConstructor(node); // Update the scope. PushScope(node.GetScope()); // Visit his children. VisitList(node.GetChildren()); // Restore the scope. PopScope(); return(node); }
public override AstNode Visit(StructDefinition node) { // Use the generic scope. PseudoScope genScope = node.GetGenericScope(); if (genScope != null) { PushScope(genScope); } // Process the base structures. node.GetStructure().SetBase(currentModule.GetValueTypeClass()); // Process the base interfaces. ProcessBases(node); // Update the scope. PushScope(node.GetScope()); // Visit his children. VisitList(node.GetChildren()); // Restore the scope. PopScope(); // Pop the generic scope. if (genScope != null) { PopScope(); } return(node); }
/// <summary> /// Generate the body of the <c>encode</c> function for the given <see cref="FieldsDefinition"/>. /// </summary> /// <param name="definition">The definition to generate code for.</param> /// <returns>The generated Dart <c>encode</c> function body.</returns> public string CompileEncode(FieldsDefinition definition) { return(definition switch { MessageDefinition d => CompileEncodeMessage(d), StructDefinition d => CompileEncodeStruct(d), _ => throw new InvalidOperationException($"invalid CompileEncode value: {definition}"), });
public void CompileBlobOfCode(string name, string code) { ICompilationEntity[] entities = this.interpreterParser.ParseText(name, code); foreach (ICompilationEntity entity in entities) { switch (entity.EntityType) { case CompilationEntityType.FUNCTION: FunctionDefinition fnDef = (FunctionDefinition)entity; string functionName = fnDef.NameToken.Value; if (this.FunctionDefinitions.ContainsKey(functionName)) { throw new ParserException(fnDef.FirstToken, "Multiple definitions of function: '" + functionName + "'"); } this.FunctionDefinitions[functionName] = fnDef; break; case CompilationEntityType.STRUCT: StructDefinition structDef = (StructDefinition)entity; string structName = structDef.NameToken.Value; if (this.StructDefinitions.ContainsKey(structName)) { throw new ParserException(structDef.FirstToken, "Multiple definitions of function: '" + structName + "'"); } this.StructDefinitions[structName] = structDef; break; case CompilationEntityType.ENUM: EnumDefinition enumDef = (EnumDefinition)entity; string enumName = enumDef.NameToken.Value; if (this.EnumDefinitions.ContainsKey(enumName)) { throw new ParserException(enumDef.FirstToken, "Multiple definitions of function: '" + enumName + "'"); } this.EnumDefinitions[enumName] = enumDef; break; case CompilationEntityType.CONSTANT: case CompilationEntityType.GLOBAL: VariableDeclaration assignment = (VariableDeclaration)entity; string targetName = assignment.VariableNameToken.Value; Dictionary <string, VariableDeclaration> lookup = entity.EntityType == CompilationEntityType.CONSTANT ? this.ConstantDefinitions : this.Globals; if (lookup.ContainsKey(targetName)) { throw new ParserException( assignment.FirstToken, "Multiple definitions of : '" + targetName + "'"); } lookup[targetName] = assignment; break; default: throw new NotImplementedException(); } } }
protected override void VisitStructField(StructDefinition @struct, StructField field) { base.VisitStructField(@struct, field); if (field.FieldType.Name == "bool") { field.FieldType.Name = "bool_t"; } }
protected override void VisitStruct(StructDefinition @struct) { base.VisitStruct(@struct); if (@struct.Name.StartsWith("LLVM") && @struct.Name.EndsWith("Ref")) { @struct.AddAttr(@"System.Diagnostics.DebuggerDisplay(""{Pointer}"")"); } }
/// <summary> /// Generate the body of the <c>encode</c> function for the given <see cref="TopLevelDefinition"/>. /// </summary> /// <param name="definition">The definition to generate code for.</param> /// <returns>The generated CPlusPlus <c>encode</c> function body.</returns> public string CompileEncode(TopLevelDefinition definition) { return(definition switch { MessageDefinition d => CompileEncodeMessage(d), StructDefinition d => CompileEncodeStruct(d), UnionDefinition d => CompileEncodeUnion(d), _ => throw new InvalidOperationException($"invalid CompileEncode kind: {definition}"), });
public async Task GenericConstraintsReturnsEmptyWhenNoConstraintsDeclared() { var node = await TestNode.FindNode <StructDeclarationSyntax>(TypeDefinitionCode.StructWithoutParent) .ConfigureAwait(false); var actual = new StructDefinition(node); actual.GenericConstraints.Should().BeEmpty(); }
internal static UserDefinedType CreateStruct(BaseTypeDeclarationSyntax node, ISyntaxEntity parent, CodeFile currentCodeFile, SyntaxTree tree) { UserDefinedType typeObj = new StructDefinition(node.Identifier.Text, new FileSpan(tree.GetLineSpan(node.Span)), parent, currentCodeFile); processModifiers(typeObj, node.Modifiers); typeObj.AccessSpecifiers = typeObj.AccessSpecifiers == AccessSpecifiers.None ? AccessSpecifiers.Internal : typeObj.AccessSpecifiers; typeObj.AssociatedComment = GetComment(typeObj, node, tree, currentCodeFile); return(typeObj); }
/// <summary> /// Write the part within the `pub struct` definition. This will just write the attributes. /// </summary> private void WriteStructDefinitionAttrs(IndentedStringBuilder builder, StructDefinition d, bool makePub = true) { foreach (var f in d.Fields) { WriteDocumentation(builder, f.Documentation); WriteDeprecation(builder, f.DeprecatedAttribute); var pub = makePub ? "pub " : ""; builder.AppendLine($"{pub}{MakeAttrIdent(f.Name)}: {TypeName(f.Type)},"); } }
private static Tuple <Node, string> GetServerReceiver(string typeName) { // make sure type is exported if (!char.IsUpper(typeName[0])) { typeName = $"{char.ToUpperInvariant(typeName[0])}{typeName.Substring(1)}"; } return(new Tuple <Node, string>(StructDefinition.Generate(typeName, null), typeName)); }
public override void GenerateCodeForStruct(TranspilerContext sb, StructDefinition structDef) { string name = structDef.NameToken.Value; sb.Append("class "); sb.Append(name); sb.Append(" {"); sb.Append(this.NewLine); sb.TabDepth++; string[] localNames = structDef.LocalFieldNames.Select(a => a.Value).ToArray(); string[] flatNames = structDef.FlatFieldNames.Select(a => a.Value).ToArray(); foreach (string fieldName in flatNames) { sb.Append(sb.CurrentTab); sb.Append("var $"); sb.Append(fieldName); sb.Append(';'); sb.Append(this.NewLine); } sb.Append(sb.CurrentTab); sb.Append("function __construct("); for (int i = 0; i < flatNames.Length; ++i) { if (i > 0) { sb.Append(", "); } sb.Append("$a"); sb.Append(i); } sb.Append(") {"); sb.Append(this.NewLine); sb.TabDepth++; for (int i = 0; i < flatNames.Length; ++i) { sb.Append(sb.CurrentTab); sb.Append("$this->"); sb.Append(flatNames[i]); sb.Append(" = $a"); sb.Append(i); sb.Append(';'); sb.Append(this.NewLine); } sb.TabDepth--; sb.Append(sb.CurrentTab); sb.Append('}'); sb.Append(this.NewLine); sb.TabDepth--; sb.Append(sb.CurrentTab); sb.Append('}'); sb.Append(this.NewLine); }
public static List <PropertyDefinition> GetColumnProperties(StructDefinition structDefinition, bool includeAutoIncrement = true) { var properties = structDefinition.Properties.Where(x => x.Attributes.Any(a => a.Name == "ColumnAttribute")).ToList(); if (!includeAutoIncrement) { properties.RemoveAll(x => x.Attributes.Any(a => a.Name == "IdentityAttribute")); } return(properties); }
public void AddStructDefinition(StructDefinition structDefinition) { if (this.structDefinitions.ContainsKey(structDefinition.Name.Value)) { throw new ParserException(structDefinition.FirstToken, "A struct with this name has already been defined."); } this.VerifyNameFree(structDefinition.Name); this.structDefinitions.Add(structDefinition.Name.Value, structDefinition); }
private void ExtractStruct(Cci.INamedTypeDefinition typedef) { var name = typedef.Name.Value; var type = new StructDefinition(name); this.ExtractGenericParameters(type.GenericParameters, typedef.GenericParameters); this.ExtractFields(type.Fields, typedef.Fields); this.ExtractMethods(type.Methods, typedef.Methods); types.Add(name, type); }
public async Task ModifiersReturnsExpectedValue(string modifiers, StructModifiers expected) { var code = EmptyStruct.Replace("public struct MyStruct", "public " + modifiers + " struct MyStruct"); var node = await TestNode.FindNode <StructDeclarationSyntax>(code) .ConfigureAwait(false); var sut = new StructDefinition(node); sut.Modifiers.Should().Be(expected); }
private void ResolveStructTypes() { foreach (string structName in this.StructDefinitions.Keys.OrderBy(t => t)) { StructDefinition structDef = this.StructDefinitions[structName]; for (int i = 0; i < structDef.LocalFieldTypes.Length; ++i) { structDef.LocalFieldTypes[i].FinalizeType(this); } } }
private void AnalyzeStrurt(StructDefinition definition) { foreach (KeyValuePair <string, DefineVariableNode> field in definition.ContainFields) { AnalyzeVarDef(field.Value); } foreach (KeyValuePair <string, FunctionDefinition> function in definition.ContainFunctions) { AnalyzeFunction(function.Value); } }
public async Task CanCreateFromDeclarationNode() { var node = await TestNode.FindNode <StructDeclarationSyntax>(EmptyStruct) .ConfigureAwait(false); var sut = new StructDefinition(node); sut.Name.Should().Be("MyStruct"); sut.Namespace.Should().Be("MyNamespace"); sut.DeclaringType.Should().BeNull(); sut.ChildStructs.Should().BeEmpty(); }
private static void ThrowUnknownVertexFormatError(StructDefinition defn) { string formatDesc = ""; foreach (var field in defn.Members) { string format = field.Name + ": " + field.Type.ToString() + "[" + field.ArraySize.ToString() + "]"; formatDesc += format + Environment.NewLine; } throw new Exception("The specified vertex format was not recognized. Format descriptor: " + Environment.NewLine + formatDesc); }
public Type SelectType(MemberDefinition member, StructDefinition defn, object parent) { var fieldName = defn.Members[0].Name; if (fieldName.Substring(0, 16) != "CurveDataHeader_") { throw new ParsingException("Unrecognized curve data header type: " + fieldName); } var curveType = fieldName.Substring(16); return(CurveRegistry.Resolve(curveType)); }
public object Read(GR2Reader reader, StructDefinition definition, MemberDefinition member, uint arraySize, object parent) { VertexDescriptor descriptor; if (!VertexTypeCache.TryGetValue(parent, out descriptor)) { descriptor = ConstructDescriptor(member, definition, parent); VertexTypeCache.Add(parent, descriptor); } var vertex = descriptor.CreateInstance(); vertex.Unserialize(reader); return(vertex); }
public async Task GenericConstraintsReturnsDeclaredConstraints() { var node = await TestNode.FindNode <StructDeclarationSyntax>(TypeDefinitionCode.StructWithGenericConstraints) .ConfigureAwait(false); var actual = new StructDefinition(node); actual.GenericConstraints.Should().HaveCount(1); var constraintList = actual.GenericConstraints.First(); constraintList.Name.Should().Be("T"); constraintList.Constraints.First().Should().Be("Stream"); constraintList.Constraints.Skip(1).First().Should().Be("new()"); }
public object Read(GR2Reader reader, StructDefinition definition, MemberDefinition member, uint arraySize, object parent) { Type type; if (!VertexTypeCache.TryGetValue(parent, out type)) { type = SelectType(member, definition, parent); VertexTypeCache.Add(parent, type); } var vertex = Helpers.CreateInstance(type); (vertex as Vertex).Unserialize(reader); return(vertex); }
public StructDefinition ReadStructDefinition() { var defn = new StructDefinition(); while (true) { var member = ReadMemberDefinition(); if (member.IsValid) defn.Members.Add(member); else break; } return defn; }
private static bool CompareType(StructDefinition defn, Type type) { var fields = type.GetFields(); if (defn.Members.Count != fields.Length) return false; for (var i = 0; i < fields.Length; i++) { if (fields[i].Name != defn.Members[i].Name) return false; if (fields[i].FieldType.IsArray) { var attrs = fields[i].GetCustomAttributes(typeof(SerializationAttribute), true); if (attrs.Length == 0) throw new InvalidOperationException("Array fields must have a valid SerializationAttribute"); var attr = attrs[0] as SerializationAttribute; if (attr.ArraySize != defn.Members[i].ArraySize) return false; } } return true; }
public void WriteStructReference(StructDefinition defn) { if (defn != null) { AddFixup(defn); if (!GR2.Types.ContainsKey(defn.Type)) { GR2.Types.Add(defn.Type, defn); } } if (GR2.Magic.Is32Bit) Writer.Write((UInt32)0); else Writer.Write((UInt64)0); }
internal void WriteStruct(StructDefinition definition, object node, bool allowRecursion = true) { if (node == null) throw new ArgumentNullException(); AlignWrite(); StoreObjectOffset(node); var tag = GR2.Header.tag; foreach (var member in definition.Members) { if (member.ShouldSerialize(tag)) { var value = member.CachedField.GetValue(node); if (member.SerializationKind == SerializationKind.UserRaw) member.Serializer.Write(this.GR2, this, member, value); else WriteInstance(member, member.CachedField.FieldType, value); } } // When the struct is empty, we need to write a dummy byte to make sure that another // struct won't have the same address. if (definition.Members.Count == 0) { Writer.Write((Byte)0); } if (Writer == MainWriter && allowRecursion) { // We need to write all child structs directly after the parent struct // (at least this is how granny2.dll does it) GR2.FlushPendingWrites(); } }
internal object Interpret(AstNode inputNode, CodeContext context) { AstNode node = inputNode; //The next node to be evaluated var flow_manager = new InterpreterFlowManager(); try{ while(true){ MAIN_LOOP: //sub-expressionを評価する必要があるノードの飛び先 switch(node.Type){ case NodeType.Argument: node = ((ParameterDeclaration)node).Option; goto MAIN_LOOP; case NodeType.Assignment: { var assignment = (AssignmentExpression)node; if(!flow_manager.IsEvaluating(assignment)){ //まず右辺値を評価する flow_manager.Push(assignment); node = assignment.Right; goto MAIN_LOOP; }else{ flow_manager.Pop(); ExpressoTuple rhs = (ExpressoTuple)flow_manager.PopValue(); for(int i = 0; i < assignment.Left.Length; ++i){ //その後左辺値に代入する var seq = (SequenceExpression)assignment.Left[i]; for(int j = 0; j < rhs.Count; ++j){ var assignable = seq.Items[j] as Assignable; if(assignable == null) throw ExpressoOps.MakeRuntimeError("{0} is not an assignable reference.", seq.Items[j]); assignable.Assign(flow_manager.Top(), rhs[j]); } } } break; } case NodeType.BinaryExpression: { var binary_op = (BinaryExpression)node; if(!flow_manager.IsEvaluating(binary_op)) flow_manager.Push(binary_op); switch(flow_manager.Top().StepCounter){ case 0: node = binary_op.Left; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = binary_op.Right; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); object rhs = flow_manager.PopValue(), lhs = flow_manager.PopValue(); if(lhs == null || rhs == null) throw ExpressoOps.MakeRuntimeError("Can not apply the operation on null objects."); object ret = null; if((int)binary_op.Operator <= (int)OperatorType.Modulus){ if(lhs is int) ret = BinaryExprAsInt((int)lhs, (int)rhs, binary_op.Operator); else if(lhs is double) ret = BinaryExprAsDouble((double)lhs, (double)rhs, binary_op.Operator); else if(lhs is Fraction) ret = BinaryExprAsFraction((Fraction)lhs, rhs, binary_op.Operator); else ret = BinaryExprAsString((string)lhs, rhs, binary_op.Operator); }else if((int)binary_op.Operator < (int)OperatorType.ConditionalAnd){ ret = EvalComparison(lhs as IComparable, rhs as IComparable, binary_op.Operator); }else if((int)binary_op.Operator < (int)OperatorType.BitwiseOr){ ret = EvalLogicalOperation((bool)lhs, (bool)rhs, binary_op.Operator); }else{ ret = EvalBitOperation((int)lhs, (int)rhs, binary_op.Operator); } flow_manager.PushValue(ret); break; } break; } case NodeType.Block: { var block = (BlockStatement)node; if(!flow_manager.IsEvaluating(block)) flow_manager.Push(block); if(flow_manager.Top().ChildCounter < block.Statements.Count){ node = block.Statements[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.BreakStatement: { var break_stmt = (BreakStatement)node; for(int i = break_stmt.Count; i > 0;){ //Count階層分ループを遡るまで出会ったbreakableをノードスタックから取り除く AstNode popped = flow_manager.Pop().TargetNode; if(popped.Type == NodeType.ForStatement || popped.Type == NodeType.WhileStatement) --i; } break; } case NodeType.Call: { var call = (CallExpression)node; if(!flow_manager.IsEvaluating(call)) flow_manager.Push(call); switch(flow_manager.Top().StepCounter){ case 0: node = call.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var fn = flow_manager.Top().Get(0) as FunctionDeclaration; if(flow_manager.Top().ChildCounter < fn.Parameters.Length){ //実引数を評価してスタックに積む var index = flow_manager.Top().ChildCounter++; var param = fn.Parameters[index]; node = (index < call.Arguments.Length) ? call.Arguments[index] : param; goto MAIN_LOOP; } flow_manager.Top().Remove(0); //呼び出す関数オブジェクトをスタックから除く node = fn.Body; flow_manager.Top().StepCounter = fn.HasReturn ? 2 : 3; goto MAIN_LOOP; case 2: var ret = flow_manager.PopValue(); flow_manager.Top().Clear(); //関数呼び出しに使ったスタック領域を解放する flow_manager.PushValue(ret); flow_manager.Pop(); break; case 3: flow_manager.Top().Clear(); //関数呼び出しに使ったスタック領域を解放する flow_manager.Pop(); break; } break; } case NodeType.CaseClause: { var case_clause = (MatchPatternClause)node; if(!flow_manager.IsEvaluating(case_clause)) flow_manager.Push(case_clause); switch(flow_manager.Top().StepCounter){ case 0: if(flow_manager.Top().ChildCounter < case_clause.Patterns.Length){ node = case_clause.Patterns[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.PushValue(false); flow_manager.Pop(); } break; case 1: var label_obj = flow_manager.PopValue(); var target = flow_manager.TopValue(); if(target is int && label_obj is ExpressoIntegerSequence){ var int_seq = (ExpressoIntegerSequence)label_obj; if(int_seq.Includes((int)target)){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter--; } }else if(label_obj is LiteralExpression && ((LiteralExpression)label_obj).Type == ObjectTypes._CASE_DEFAULT){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else if(label_obj != null && label_obj.Equals(target)){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter--; } break; case 2: flow_manager.Pop(); flow_manager.PushValue(true); break; } break; } case NodeType.CastExpression: { var cast_expr = (CastExpression)node; if(!flow_manager.IsEvaluating(cast_expr)) flow_manager.Push(cast_expr); switch(flow_manager.Top().StepCounter){ case 0: node = cast_expr.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = cast_expr.ToExpression; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); var to_expr = flow_manager.PopValue(); var target = flow_manager.PopValue(); break; } break; } case NodeType.CatchClause: { var catch_clause = (CatchClause)node; var exception = flow_manager.TopValue() as ExpressoThrowException; if(exception == null){ throw ExpressoOps.MakeSystemError("The top value of stack is not an exception."); }else if(catch_clause.Catcher.ParamType.TypeName == exception.Thrown.Name){ node = catch_clause.Body; goto case NodeType.Block; } break; } case NodeType.Comprehension: //TODO:実装する { break; } case NodeType.ComprehensionFor: { break; } case NodeType.ComprehensionIf: { var comp_if = (ComprehensionIfClause)node; if(!flow_manager.IsEvaluating(comp_if)) flow_manager.Push(comp_if); switch(flow_manager.Top().StepCounter){ case 0: node = comp_if.Condition; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var cond = flow_manager.TopValue(); if(!(cond is bool)) throw ExpressoOps.MakeInvalidTypeError("Can not evaluate the expression to a boolean."); if((bool)cond){ var yield_expr = flow_manager.Top().Get(0) as Expression; node = (comp_if.Body == null) ? yield_expr : comp_if.Body; flow_manager.Pop(); goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } break; } case NodeType.ConditionalExpression: { var cond_expr = (ConditionalExpression)node; if(!flow_manager.IsEvaluating(cond_expr)){ node = cond_expr.Condition; flow_manager.Push(cond_expr); }else{ flow_manager.Pop(); node = (bool)flow_manager.PopValue() ? cond_expr.TrueExpression : cond_expr.FalseExpression; } goto MAIN_LOOP; } case NodeType.Constant: flow_manager.PushValue(((LiteralExpression)node).Value); break; case NodeType.ContinueStatement: { var continue_stmt = (ContinueStatement)node; for(int i = continue_stmt.Count; i > 0;){ //Count階層分ループを遡るまで出会ったbreakableをノードスタックから取り除く AstNode popped = flow_manager.Pop().TargetNode; if(popped.Type == NodeType.ForStatement || popped.Type == NodeType.WhileStatement && i != 1) //continueすべきループはスタックから外さない --i; } break; } case NodeType.DefaultExpression: { var default_expr = (DefaultExpression)node; flow_manager.PushValue(ExpressoOps.GetDefaultValueFor(default_expr.TargetType.ObjType)); break; } case NodeType.ExprStatement: { var expr_stmt = (ExpressionStatement)node; if(!flow_manager.IsEvaluating(expr_stmt)) flow_manager.Push(expr_stmt); if(flow_manager.Top().ChildCounter < expr_stmt.Expressions.Length){ node = expr_stmt.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.FinallyClause: { var finally_clause = (FinallyClause)node; node = finally_clause.Body; goto case NodeType.Block; } case NodeType.ForStatement: { var for_stmt = (ForStatement)node; if(!flow_manager.IsEvaluating(for_stmt)) flow_manager.Push(for_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = for_stmt.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: { object iterable = flow_manager.TopValue(); if(!(iterable is IEnumerable)) throw ExpressoOps.MakeInvalidTypeError("Can not evaluate the expression to an iterable object!"); Identifier[] lvalues = new Identifier[for_stmt.Left.Count]; for(int i = 0; i < for_stmt.Left.Count; ++i){ lvalues[i] = for_stmt.Left.Items[i] as Identifier; if(lvalues[i] == null) throw ExpressoOps.MakeReferenceError("The left-hand-side of the \"in\" keyword must be a lvalue(a referencible value such as variables)"); } flow_manager.PushValue(lvalues); flow_manager.Top().StepCounter++; goto case 2; } case 2: Identifier[] lhs = (Identifier[])flow_manager.TopValue(); object iterable_obj = flow_manager.GetValue(flow_manager.ValueCount - 2); var rvalue = ExpressoOps.Enumerate(iterable_obj); if(rvalue.MoveNext()){ for(int j = 0; j < lhs.Length; ++j){ lhs[j].Assign(flow_manager.Top(), rvalue.Current); if(j + 1 != lhs.Length){ if(!rvalue.MoveNext()) throw ExpressoOps.MakeRuntimeError("The number of rvalues must be some multiple of that of lvalues."); } } node = for_stmt.Body; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } break; } case NodeType.FunctionDef: //node = ((FunctionDefinition)node).Body; //goto MAIN_LOOP; flow_manager.PushValue(node); break; case NodeType.Identifier: { var ident = (Identifier)node; if(ident.Type.ObjType == ObjectTypes._Subscript){ flow_manager.PushValue(ident); }else if(ident.IsResolved){ flow_manager.Top().Dup(ident.Offset); }else if(ident.ParamType.ObjType == ObjectTypes.TypeClass){ var cur_module = flow_manager.Top().Get(0) as ExpressoObj; if(cur_module == null) throw ExpressoOps.MakeRuntimeError("\"this\" doesn't refer to the enclosing class instance."); flow_manager.PushValue(cur_module.AccessMember(ident, true)); }else if(ident.ParamType.ObjType == ObjectTypes.TypeModule){ var module = context.LanguageContext.GetModule(ident.Name); if(module == null) throw ExpressoOps.MakeRuntimeError(string.Format("The requested module \"{0}\" doesn't exist.", ident.Name)); flow_manager.PushValue(module); } break; } case NodeType.IfStatement: { var if_stmt = (IfStatement)node; if(!flow_manager.IsEvaluating(if_stmt)){ node = if_stmt.Condition; flow_manager.Push(if_stmt); }else{ flow_manager.Pop(); node = (bool)flow_manager.PopValue() ? if_stmt.TrueBlock : if_stmt.FalseBlock; } goto MAIN_LOOP; } case NodeType.Initializer: { var initializer = (SequenceInitializer)node; if(!flow_manager.IsEvaluating(initializer)) flow_manager.Push(initializer); if(flow_manager.Top().ChildCounter < initializer.Items.Length){ node = initializer.Items[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); switch(initializer.ObjectType){ case ObjectTypes.List: { var values = new List<object>(initializer.Items.Length); for(int i = initializer.Items.Length; i > 0; --i) values.Add(flow_manager.PopValue()); values.Reverse(); //スタックからポップした順番では、逆順になってしまうので、順序を入れ替える flow_manager.PushValue(ExpressoOps.MakeList(values)); break; } case ObjectTypes.Tuple: { var values = new List<object>(initializer.Items.Length); for(int i = initializer.Items.Length; i > 0; --i) values.Add(flow_manager.PopValue()); values.Reverse(); //スタックからポップした順番では、逆順になってしまうので、順序を入れ替える flow_manager.PushValue(ExpressoOps.MakeTuple(values)); break; } case ObjectTypes.Dict: { var keys = new List<object>(initializer.Items.Length / 2); var values = new List<object>(initializer.Items.Length / 2); for(int i = initializer.Items.Length; i > 0; --i){ if(i % 2 == 1) keys.Add(flow_manager.PopValue()); else values.Add(flow_manager.PopValue()); } keys.Reverse(); //スタックからポップした順番では逆順になってしまうので、順序を入れ替える values.Reverse(); flow_manager.PushValue(ExpressoOps.MakeDict(keys, values)); break; } default: throw ExpressoOps.MakeRuntimeError("Unknown type of initializer!"); } } break; } case NodeType.MemRef: { var mem_ref = (MemberReference)node; if(!flow_manager.IsEvaluating(mem_ref)) flow_manager.Push(mem_ref); switch(flow_manager.Top().StepCounter){ case 0: node = mem_ref.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = mem_ref.Subscription; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); var subscription = flow_manager.PopValue(); var obj = flow_manager.PopValue(); if(subscription is ExpressoIntegerSequence){ var seq = (ExpressoIntegerSequence)subscription; flow_manager.PushValue(ExpressoOps.Slice(obj, seq)); }else if(obj is ExpressoObj){ var exs_obj = (ExpressoObj)obj; var member = exs_obj.AccessMember(subscription, obj == flow_manager.Top().Get(0)); flow_manager.PushValue(member); }else{ var member = ExpressoOps.AccessMember(obj, subscription); flow_manager.PushValue(member); } break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a member reference expression!"); } break; } case NodeType.Toplevel: { var toplevel = (ExpressoAst)node; if(!flow_manager.IsEvaluating(toplevel)) flow_manager.Push(toplevel); if(flow_manager.Top().ChildCounter < toplevel.Body.Length){ node = toplevel.Body[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ if(toplevel.IsModule){ var internals = new Dictionary<string, int>(); var exported = new Dictionary<string, int>(); Dictionary<string, int> decl_target = null; var members = new List<object>(); int offset = 0; for(int i = 0; i < toplevel.Body.Length; ++i){ decl_target = toplevel.ExportMap.Get(i) ? exported : internals; var stmt = toplevel.Body[i]; object val = flow_manager.Top().Get(offset); if(stmt is ExpressionStatement){ var expr_stmt = (ExpressionStatement)stmt; if(expr_stmt.Expressions[0] is VariableDeclarationStatement){ var var_decls = (VariableDeclarationStatement)expr_stmt.Expressions[0]; for(int j = 0; j < var_decls.Left.Length; ++j){ val = flow_manager.Top().Get(offset); decl_target.Add(var_decls.Left[j].Name, offset++); members.Add(val); //val = flow_manager.Top().Get(offset); //varStore.Add(var_decls.Variables[i].Offset, obj); //モジュールスコープの変数ストアにも実体を追加しておく } }else{ throw ExpressoOps.MakeInvalidTypeError("A module declaration can not have that type of statements!"); } }else if(stmt is FunctionDeclaration){ var method = (FunctionDeclaration)stmt; decl_target.Add(method.Name, offset++); members.Add(val); }else if(stmt is TypeDefinition){ var type_decl = (TypeDefinition)stmt; var type_def = flow_manager.Top().Get(offset); decl_target.Add(type_decl.Name, offset++); members.Add(type_def); }else{ throw ExpressoOps.MakeInvalidTypeError("A module declaration can not have that type of statements!"); } } var module_def = new ModuleDefinition(toplevel.ModuleName, internals, exported, members.ToArray()); var module_inst = new ExpressoModule(module_def); context.LanguageContext.PublishModule(toplevel.ModuleName, module_inst); } flow_manager.Pop(); } break; } case NodeType.New: { var new_expr = (NewExpression)node; if(!flow_manager.IsEvaluating(new_expr)){ node = new_expr.CreationExpression; flow_manager.Push(new_expr); goto MAIN_LOOP; }else{ flow_manager.Pop(); var type_def = flow_manager.PopValue() as BaseDefinition; if(type_def == null) throw ExpressoOps.MakeInvalidTypeError("{0} doesn't refer to a type name.", new_expr.CreationExpression); flow_manager.PushValue(ExpressoObj.CreateInstance(null, type_def, new_expr.Arguments)); } break; } case NodeType.Print: { var print_stmt = (PrintStatement)node; if(!flow_manager.IsEvaluating(print_stmt)) flow_manager.Push(print_stmt); if(flow_manager.Top().ChildCounter < print_stmt.Expressions.Length){ node = print_stmt.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); var values = new List<object>(print_stmt.Expressions.Length); for(int i = print_stmt.Expressions.Length; i > 0; --i) values.Add(flow_manager.PopValue()); ExpressoOps.DoPrint(values, print_stmt.HasTrailing); } break; } case NodeType.Require: { var require_expr = (ImportDeclaration)node; foreach(var module_name in require_expr.ModuleNames){ var path = module_name.Replace('.', '/'); path += ".exs"; path = GetRelativePathToCurrentSource(path); var module_parser = new Parser(new Scanner(path)); module_parser.ParsingFileName = module_name; module_parser.Parse(); Interpret(module_parser.TopmostAst, context); } break; } case NodeType.Return: { var return_stmt = (ReturnStatement)node; if(return_stmt.Expression != null){ if(!flow_manager.IsEvaluating(return_stmt)){ flow_manager.Push(return_stmt); node = return_stmt.Expression; goto MAIN_LOOP; }else{ flow_manager.Pop(); ExpressoTuple ret = (ExpressoTuple)flow_manager.PopValue(); if(ret.Count == 1) flow_manager.PushValue(ret[0]); else flow_manager.PushValue(ret); } } break; } case NodeType.IntSequence: { var intseq_expr = (IntegerSequenceExpression)node; if(!flow_manager.IsEvaluating(intseq_expr)) flow_manager.Push(intseq_expr); switch(flow_manager.Top().StepCounter){ case 0: node = intseq_expr.Lower; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = intseq_expr.Upper; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: node = intseq_expr.Step; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 3: flow_manager.Pop(); var step = flow_manager.PopValue(); var end = flow_manager.PopValue(); var start = flow_manager.PopValue(); if(!(start is int) || !(end is int) || !(step is int)) throw ExpressoOps.MakeInvalidTypeError("The start, end and step expressions of the IntSeq expression must yield an integer."); flow_manager.PushValue(new ExpressoIntegerSequence((int)start, (int)end, (int)step)); break; default: throw ExpressoOps.MakeSystemError("An error occurred while evaluating an IntegerSequence expression."); } break; } case NodeType.Sequence: { var seq_expr = (SequenceExpression)node; if(!flow_manager.IsEvaluating(seq_expr)) flow_manager.Push(seq_expr); if(flow_manager.Top().ChildCounter < seq_expr.Count){ node = seq_expr.Items[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); var item_values = new object[seq_expr.Count]; for(int i = seq_expr.Count - 1; i >= 0; --i) item_values[i] = flow_manager.PopValue(); flow_manager.PushValue(ExpressoOps.MakeTuple(item_values)); } break; } case NodeType.SwitchStatement: { var switch_stmt = (MatchStatement)node; if(!flow_manager.IsEvaluating(switch_stmt)) flow_manager.Push(switch_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = switch_stmt.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: if(flow_manager.Top().ChildCounter < switch_stmt.Clauses.Length){ if(flow_manager.Top().ChildCounter != 0){ object top = flow_manager.PopValue(); if(top is bool && (bool)top) goto CLEANUP_SWITCH; } node = switch_stmt.Clauses[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } CLEANUP_SWITCH: flow_manager.PopValue(); //caseラベルと照合する値をスタックから外す break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a switch statement!"); } break; } case NodeType.ThrowStatement: { var throw_stmt = (ThrowStatement)node; if(!flow_manager.IsEvaluating(throw_stmt)){ node = throw_stmt.Expression; flow_manager.Push(throw_stmt); goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.TryStatement: { var try_stmt = (TryStatement)node; if(!flow_manager.IsEvaluating(try_stmt)){ node = try_stmt.Body; flow_manager.Push(try_stmt); goto case NodeType.Block; }else{ //ノードスタックのトップがこのtry文だった場合、try文の本体の実行は終わっている var top = flow_manager.TopValue(); if(top is ExpressoThrowException){ if(try_stmt.Catches != null){ node = try_stmt.Catches[flow_manager.Top().ChildCounter++]; goto case NodeType.CatchClause; }else{ flow_manager.Pop(); while(flow_manager.Count > 0){ //一つ上のtry文にたどり着くまでノードスタックを巻き戻す flow_manager.Pop(); if(flow_manager.Top().TargetNode.Type == NodeType.TryStatement) break; //NOTE: 次のループに入る前に親のノードを参照するので、ここでは何もしない } if(flow_manager.Count == 0) //このtry文を内包するtry文が見つからなかったので、C#側の例外ハンドラに処理を投げる throw (ExpressoThrowException)top; } } if(try_stmt.FinallyClause != null){ node = try_stmt.FinallyClause; if(flow_manager.IsEvaluating(try_stmt)) //finally節を実行したらこのtry文には用はなくなる flow_manager.Pop(); goto case NodeType.FinallyClause; } flow_manager.Pop(); //ここに到達するのはfinally節がなく、try文の本体で例外が発生しなかった場合だけ } break; } case NodeType.TypeDef: { var type_def = (TypeDefinition)node; if(!flow_manager.IsEvaluating(type_def)) flow_manager.Push(type_def); switch(flow_manager.Top().StepCounter){ case 0: if(flow_manager.Top().ChildCounter < type_def.Bases.Length){ node = type_def.Bases[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Top().ChildCounter = 0; flow_manager.Top().StepCounter++; goto case 1; } case 1: if(flow_manager.Top().ChildCounter < type_def.Body.Length){ node = type_def.Body[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter++; goto case 2; } case 2: var private_members = new Dictionary<string, int>(); var public_members = new Dictionary<string, int>(); var members = new List<object>(); int offset = 0; for(int i = 0; i < type_def.Body.Length; ++i){ var stmt = type_def.Body[i]; object val = flow_manager.Top().Get(offset); if(stmt is ExpressionStatement){ var expr_stmt = (ExpressionStatement)stmt; if(expr_stmt.Expressions[0] is VariableDeclarationStatement){ var var_decls = (VariableDeclarationStatement)expr_stmt.Expressions[0]; for(int j = 0; j < var_decls.Left.Length; ++j){ val = flow_manager.Top().Get(offset); if(var_decls.HasFlag(Flags.PrivateAccess)) private_members.Add(var_decls.Left[j].Name, offset++); else if(var_decls.HasFlag(Flags.PublicAccess)) public_members.Add(var_decls.Left[j].Name, offset++); members.Add(val); } }else{ throw ExpressoOps.MakeInvalidTypeError("A type declaration can not have that type of statements!"); } }else if(stmt is FunctionDeclaration){ var method = (FunctionDeclaration)stmt; if(method.HasFlag(Flags.PrivateAccess)) private_members.Add(method.Name, offset++); else if(method.HasFlag(Flags.PublicAccess)) public_members.Add(method.Name, offset++); members.Add(val); }else{ throw ExpressoOps.MakeInvalidTypeError("A type declaration can not have that type of statements!"); } } //継承元の型定義をスタックから参照する var base_definitions = new List<BaseDefinition>(); for(int i = 0; i < type_def.Bases.Length; ++i){ BaseDefinition base_def = flow_manager.Top().Get(i) as BaseDefinition; if(base_def == null){ throw ExpressoOps.MakeRuntimeError("Something wrong has occurred.\n Could not find base type '{0}'", type_def.Bases[i].Name); } base_definitions.Add(base_def); } object def_object = null; switch(type_def.TargetType){ case DeclType.Interface: def_object = new InterfaceDefinition(type_def.Name, public_members, members.ToArray(), base_definitions); break; case DeclType.Class: def_object = new ClassDefinition(type_def.Name, private_members, public_members, members.ToArray(), base_definitions); break; case DeclType.Struct: def_object = new StructDefinition(type_def.Name, private_members, public_members, members.ToArray(), base_definitions); break; } flow_manager.PushValue(def_object); flow_manager.Pop(); break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a type definition."); } break; } case NodeType.UnaryExpression: { var unary_op = (UnaryExpression)node; if(!flow_manager.IsEvaluating(unary_op)){ node = unary_op.Operand; flow_manager.Push(unary_op); goto MAIN_LOOP; }else{ flow_manager.Pop(); var ope = flow_manager.PopValue(); if(ope == null) throw ExpressoOps.MakeInvalidTypeError("Invalid object type!"); flow_manager.PushValue(EvalUnaryOperation(unary_op.Operator, ope)); } break; } case NodeType.VarDecl: { var var_decl = (VariableDeclarationStatement)node; if(!flow_manager.IsEvaluating(var_decl)) flow_manager.Push(var_decl); int child_counter = flow_manager.Top().ChildCounter; if(child_counter < var_decl.Left.Length){ node = var_decl.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.WhileStatement: { var while_stmt = (WhileStatement)node; if(!flow_manager.IsEvaluating(while_stmt)) flow_manager.Push(while_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = while_stmt.Condition; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var cond = flow_manager.PopValue(); try{ if(cond != null && (bool)cond){ node = while_stmt.Body; flow_manager.Top().StepCounter--; goto MAIN_LOOP; }else{ flow_manager.Pop(); } } catch(Exception){ if(!(cond is bool)) throw ExpressoOps.MakeInvalidTypeError("Invalid expression! The condition of a while statement must yield a boolean!"); } break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a while statement!"); } break; } case NodeType.WithStatement: break; case NodeType.YieldStatement: break; default: throw ExpressoOps.MakeRuntimeError("Unknown AST type!"); } if(flow_manager.Count != 0) node = flow_manager.Top().TargetNode; else break; //評価スタックがなくなったので、ループを抜ける } } catch(Exception ex){ Type exception_type = ex.GetType(); Console.WriteLine("{0}: {1}", exception_type.FullName, ex.Message); Console.WriteLine("Stack trace: {0}", ex.StackTrace); } Debug.Assert(flow_manager.ValueCount == 0 || flow_manager.ValueCount == 1); return (flow_manager.ValueCount > 0) ? flow_manager.PopValue() : null; }
public object Read(GR2Reader reader, StructDefinition definition, MemberDefinition member, uint arraySize, object parent) { Type type; if (!VertexTypeCache.TryGetValue(parent, out type)) { type = SelectType(member, definition, parent); VertexTypeCache.Add(parent, type); } var vertex = Helpers.CreateInstance(type); (vertex as Vertex).Unserialize(reader); return vertex; }
internal void AddMixedMarshalling(object o, UInt32 count, StructDefinition type) { var marshal = new MixedMarshallingData(); marshal.Obj = o; marshal.Count = count; marshal.Type = type; MixedMarshalling.Add(marshal); }
internal StructDefinition LookupStructDefinition(Type type) { if (type.GetInterfaces().Contains(typeof(System.Collections.IList)) || type.IsArray || type.IsPrimitive) throw new ArgumentException("Cannot create a struct definition for array or primitive types"); StructDefinition defn = null; if (!Types.TryGetValue(type, out defn)) { defn = new StructDefinition(); Types.Add(type, defn); defn.LoadFromType(type, this); } return defn; }
private void MixedMarshal(UInt32 count, StructDefinition definition) { for (var arrayIdx = 0; arrayIdx < count; arrayIdx++) { foreach (var member in definition.Members) { var size = member.Size(this); if (member.Type == MemberType.Inline) { MixedMarshal(member.ArraySize == 0 ? 1 : member.ArraySize, member.Definition.Resolve(this)); } else if (member.MarshallingSize() > 1) { var marshalSize = member.MarshallingSize(); byte[] data = new byte[size]; Stream.Read(data, 0, (int)size); for (var j = 0; j < size / marshalSize; j++) { // Byte swap for 2, 4, 8-byte values for (var off = 0; off < marshalSize / 2; off++) { var tmp = data[j * marshalSize + off]; data[j * marshalSize + off] = data[j * marshalSize + marshalSize - 1 - off]; data[j * marshalSize + marshalSize - 1 - off] = tmp; } } Stream.Seek(-size, SeekOrigin.Current); Stream.Write(data, 0, (int)size); Stream.Seek(-size, SeekOrigin.Current); } Stream.Seek(size, SeekOrigin.Current); } } }
public static Type FindByStruct(StructDefinition defn) { Init(); foreach (var proto in PrototypeMap) { if (CompareType(defn, proto.Key)) { return proto.Value; } } ThrowUnknownVertexFormatError(defn); return null; }
public void WriteStructDefinition(StructDefinition defn) { Debug.Assert(Writer == MainWriter); GR2.ObjectOffsets[defn] = new SectionReference(Type, (UInt32)MainStream.Position); var tag = GR2.Header.tag; foreach (var member in defn.Members) { if (member.ShouldSerialize(tag)) { WriteMemberDefinition(member); } } var end = new MemberDefinition(); end.Type = MemberType.None; end.Extra = new UInt32[] { 0, 0, 0 }; WriteMemberDefinition(end); }
internal object ReadStruct(StructDefinition definition, MemberType memberType, object node, object parent) { var offset = (UInt32)Stream.Position; object cachedNode = null; if (memberType != MemberType.Inline && CachedStructs.TryGetValue(offset, out cachedNode)) { #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format("Skipped cached struct {1} at {0:X8}", offset, node.ToString())); #endif Stream.Position += definition.Size(this); return cachedNode; } if (node != null) { // Don't save inline structs in the cached struct map, as they can occupy the same address as a non-inline struct // if they're at the beginning of said struct. // They also cannot be referenced from multiple locations, so caching them is of no use. if (memberType != MemberType.Inline) CachedStructs.Add(offset, node); #if DEBUG_GR2_FORMAT_DIFFERENCES // Create a struct definition from this instance and check if the GR2 type differs from the local type. var localDefn = new StructDefinition(); localDefn.LoadFromType(node.GetType(), null); var localMembers = localDefn.Members.Where(m => m.ShouldSerialize(Header.tag)).ToList(); var defnMembers = definition.Members.Where(m => m.ShouldSerialize(Header.tag)).ToList(); if (localMembers.Count != defnMembers.Count) { Trace.TraceWarning(String.Format("Struct {0} differs: Field count differs ({1} vs {2})", node.GetType().Name, localMembers.Count, defnMembers.Count)); } else { for (int i = 0; i < localMembers.Count; i++) { var member = localMembers[i]; var local = defnMembers[i]; if (member.Type != local.Type) { Trace.TraceWarning(String.Format( "Struct {0}: Field {1} type differs ({1} vs {2})", node.GetType().Name, local.Name, local.Type, member.Type )); } if (!member.GrannyName.Equals(local.GrannyName)) { Trace.TraceWarning(String.Format( "Struct {0}: Field {1} name differs ({1} vs {2})", node.GetType().Name, local.Name, local.GrannyName, member.GrannyName )); } if (member.ArraySize != local.ArraySize) { Trace.TraceWarning(String.Format( "Struct {0}: Field {1} array size differs ({1} vs {2})", node.GetType().Name, local.Name, local.ArraySize, member.ArraySize )); } } } #endif definition.MapType(node); foreach (var member in definition.Members) { var field = member.LookupFieldInfo(node); if (field != null) { var value = ReadInstance(member, field.GetValue(node), field.FieldType, node); field.SetValue(node, value); } else { ReadInstance(member, null, null, node); } } } else { foreach (var member in definition.Members) { ReadInstance(member, null, null, null); } } return node; }
public Type SelectType(MemberDefinition member, StructDefinition defn, object parent) { return VertexFormatRegistry.FindByStruct(defn); }