public State(String name, CodeBody body, List<Specifier> specs, State parent, List<Function> funcs, List<Function> ignores, List<StateLabel> labels, SourcePosition start, SourcePosition end) : base(ASTNodeType.State, start, end) { Name = name; Body = body; Specifiers = specs; Parent = parent; Functions = funcs; Ignores = ignores; Labels = labels; Locals = new List<VariableDeclaration>(); }
public bool VisitNode(State node) { if (Symbols.SymbolExistsInCurrentScope(node.Name)) return Error("The name '" + node.Name + "' is already in use in this class!", node.StartPos, node.EndPos); ASTNode overrideState; bool overrides = Symbols.TryGetSymbol(node.Name, out overrideState, NodeUtils.GetOuterClassScope(node)) && overrideState.Type == ASTNodeType.State; if (node.Parent != null) { if (overrides) return Error("A state is not allowed to both override a parent class's state and extend another state at the same time!", node.StartPos, node.EndPos); ASTNode parent; if (!Symbols.TryGetSymbolFromCurrentScope(node.Parent.Name, out parent)) Error("No parent state named '" + node.Parent.Name + "' found in the current class!", node.Parent.StartPos, node.Parent.EndPos); if (parent != null) { if (parent.Type != ASTNodeType.State) Error("Parent named '" + node.Parent.Name + "' is not a state!", node.Parent.StartPos, node.Parent.EndPos); else node.Parent = parent as State; } } int numFuncs = node.Functions.Count; Symbols.PushScope(node.Name); foreach (Function ignore in node.Ignores) { ASTNode original; if (!Symbols.TryGetSymbol(ignore.Name, out original, "") || original.Type != ASTNodeType.Function) return Error("No function to ignore named '" + ignore.Name + "' found!", ignore.StartPos, ignore.EndPos); Function header = original as Function; Function emptyOverride = new Function(header.Name, header.ReturnType, new CodeBody(null, null, null), header.Specifiers, header.Parameters, ignore.StartPos, ignore.EndPos); node.Functions.Add(emptyOverride); Symbols.AddSymbol(emptyOverride.Name, emptyOverride); } foreach (Function func in node.Functions.GetRange(0, numFuncs)) { func.Outer = node; Success = Success && func.AcceptVisitor(this); } //TODO: check functions overrides: //if the state overrides another state, we should be in that scope as well whenh we check overrides maybe? //if the state has a parent state, we should be in that scope //this is a royal mess, check that ignores also look-up from parent/overriding states as we are not sure if symbols are in the scope // if the state extends a parent state, use that as outer in the symbol lookup // if the state overrides another state, use that as outer // both of the above should apply to functions as well as ignores. //TODO: state code/labels Symbols.PopScope(); return Success; }
public bool VisitNode(State node) { // [specifiers] state statename [extends parentstruct] { \n contents \n }; Write(""); if (node.Specifiers.Count > 0) Append("{0} ", String.Join(" ", node.Specifiers.Select(x => x.Value))); Append("state {0} ", node.Name); if (node.Parent != null) Append("extends {0} ", node.Parent.Name); Append("{0}", "{"); NestingLevel++; if (node.Ignores.Count > 0) Write("ignores {0};", String.Join(", ", node.Ignores.Select(x => x.Name))); foreach (Function func in node.Functions) func.AcceptVisitor(this); if (node.Body.Statements.Count != 0) { Write(""); Write("// State code"); node.Body.AcceptVisitor(this); } NestingLevel--; Write("{0};", "}"); return true; }
public State ConvertState(ME3State obj) { // TODO: ignores and body/labels State parent = null; if (obj.SuperField != null) parent = new State(obj.SuperField.Name, null, null, null, null, null, null, null, null); var Funcs = new List<Function>(); var Ignores = new List<Function>(); foreach (var member in obj.DefinedFunctions) { if (member.FunctionFlags.HasFlag(FunctionFlags.Defined)) Funcs.Add(ConvertFunction(member)); else Ignores.Add(new Function(member.Name, null, null, null, null, null, null)); /* Ignored functions are not marked as defined, so we dont need to lookup the ignormask. * They are defined though, each being its own proper object with simply a return nothing for bytecode. * */ } var ByteCode = new ME3ByteCodeDecompiler(obj, new List<FunctionParameter>()); var body = ByteCode.Decompile(); return new State(obj.Name, body, new List<Specifier>(), (State)parent, Funcs, new List<Function>(), new List<StateLabel>(), null, null); }