public void Add(ISledLuaVarBaseType luaVar) { if (luaVar == null) { return; } m_dictCustomWatches[luaVar] = WatchedVariableService.ReceivingWatchedCustomVariables; if (luaVar.DomNode.Is <SledLuaVarGlobalType>()) { Globals.Add(luaVar.DomNode.As <SledLuaVarGlobalType>()); } else if (luaVar.DomNode.Is <SledLuaVarLocalType>()) { Locals.Add(luaVar.DomNode.As <SledLuaVarLocalType>()); } else if (luaVar.DomNode.Is <SledLuaVarUpvalueType>()) { Upvalues.Add(luaVar.DomNode.As <SledLuaVarUpvalueType>()); } else if (luaVar.DomNode.Is <SledLuaVarEnvType>()) { EnvVars.Add(luaVar.DomNode.As <SledLuaVarEnvType>()); } }
public static LocalObjectDef AllocateLocal(Type type, string name = "") { List <LocalObjectDef> duplicatedLocals = new List <LocalObjectDef>(); int number = 0; int i; for (i = 0; i < Locals.Count; i++) { if (Locals[i].Scope == ObjectScope.Local && (Locals[i] as LocalObjectDef).Name == name && name != "") { duplicatedLocals.Add(Locals[i] as LocalObjectDef); Locals[i].IsUsed = false; } } for (i = 0; i < Locals.Count; i++) { if (Locals[i].Type.Name == type.Name && !Locals[i].IsUsed) { number = i; Locals[i] = new LocalObjectDef(type, number, name); break; } } if (i == Locals.Count) { var localVar = iLGenerator.DeclareLocal(type); number = localVar.LocalIndex; Locals.Add(new LocalObjectDef(type, number, name)); } EmitSaveToLocal(number); return(Locals[number]); }
public LocalBuilderInfo AddLocal(string name, LocalBuilder builder) { LocalBuilderInfo info = new LocalBuilderInfo(Locals.Count, name, builder); Locals.Add(name, info); return(info); }
public Catch(Type exception, Lambda filter, IEnumerable <Node> nodes) : base(NodeType.Catch, nodes) { ExceptionType = exception; Filter = filter ?? new Lambda(typeof(Exception), typeof(bool)); Locals.Add(new Local("$exn", null)); }
public void Set <T>(string name, T value) { var pyName = name; var pyObj = value; Locals.Add(pyName, pyObj); }
private bool Visit(DeclareLocalStatement stmt) { var value = stmt.Initializer == null ? new BitsValue(0, stmt.Local.BitSize) : Visit(stmt.Initializer); Locals.Add(stmt.Local.Name, value); return(false); }
Variable StoreTempDontDup(DataType dt) { var v = new Variable(Function.Source, Function, "#temp" + (_tempVariableCounter++), dt); Locals.Add(v); Emit(Opcodes.StoreLocal, v); return(v); }
void CreateIndirection(DataType dt) { var v = new Variable(Function.Source, Function, "#ind" + (_tempVariableCounter++), dt); Locals.Add(v); Emit(Opcodes.StoreLocal, v); Emit(Opcodes.LoadLocalAddress, v); }
public IZ_FOR(int numberOfInterations) { if (Locals["Index"] == null) { Locals.Add(new Variables.LocalsVariable { Name = "Index", VariableType = typeof(Int32), Value = 0 }); } }
public override void Parse(TokensStack sTokens) { Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; Token t = sTokens.Pop(); //( while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) //) { if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); if (sTokens.Count > 0 && sTokens.Peek() is Separator)//, { sTokens.Pop(); } } t = sTokens.Pop(); //) t = sTokens.Pop(); //{ while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); local.Parse(sTokens); Locals.Add(local); } while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); s.Parse(sTokens); Body.Add(s); } Token tEnd = sTokens.Pop();//} }
Variable StoreTemp(DataType dt, bool pop) { if (pop) { return(null); } var v = new Variable(Function.Source, Function, "#temp" + (_tempVariableCounter++), dt); Locals.Add(v); Emit(Opcodes.Dup); Emit(Opcodes.StoreLocal, v); return(v); }
public void AddVariable(string name, object value) { var nameIdx = LocalNames.IndexOf(name); if (nameIdx == -1) { LocalNames.Add(name); Locals.Add(value); } else { Locals[nameIdx] = value; } }
private void EmitArrayCreationWithInitializer() { var localBuilder = ILGenerator.DeclareLocal(Type); Locals.Add(localBuilder); Node.Initializer.AcceptVisitor(Visitor, ILGenerator); Node.Arguments.ForEach(arg => arg.AcceptVisitor(this, ILGenerator)); if (TryEmitNewObject()) { ILGenerator.EmitStoreLocal(localBuilder); } }
public LingoHandler(LingoScriptChunk script, ref ShockwaveReader input) : this(script) { NameIndex = input.ReadInt16(); HandlerVectorPosition = input.ReadInt16(); Body = new LingoHandlerBody(this, ref input); int codeOffset = input.ReadInt32(); Arguments.Capacity = input.ReadInt16(); int argumentsOffset = input.ReadInt32(); Locals.Capacity = input.ReadInt16(); int localsOffset = input.ReadInt32(); input.ReadInt16(); //offset(?) input.ReadInt32(); //length(?) input.ReadInt32(); //offset? input.ReadInt16(); //length? BytesPerLine.Capacity = input.ReadInt16(); int lineOffset = input.ReadInt32(); Body.StackHeight = input.ReadInt32(); int handlerEndOffset = input.Position; input.Position = codeOffset; input.ReadBytes(Body.Code); input.Position = argumentsOffset; for (int i = 0; i < Arguments.Capacity; i++) { Arguments.Add(input.ReadInt16()); } input.Position = localsOffset; for (int i = 0; i < Locals.Capacity; i++) { Locals.Add(input.ReadInt16()); } input.Position = lineOffset; for (int i = 0; i < BytesPerLine.Capacity; i++) { BytesPerLine.Add(input.ReadByte()); } input.Position = handlerEndOffset; }
private void EmitVariableDeclarationStatement(CodeVariableDeclarationStatement Statement) { if (Locals.ContainsKey(Statement.Name)) { throw new CompileException(Statement, "Attempt to redefine local variable " + Statement.Name); } Type Top = EmitExpression(Statement.InitExpression); LocalBuilder Local = Generator.DeclareLocal(Top); Locals.Add(Statement.Name, Local); Generator.Emit(OpCodes.Stloc, Local); }
protected internal override void EmitPrivateReference() { Type fieldInfoType = typeof(FieldInfo); Type typeOfSystemType = typeof(Type); var localBuilder = ILGenerator.DeclareLocal(fieldInfoType); Locals.Add(localBuilder); ILGenerator.Emit(OpCodes.Ldtoken, Target); ILGenerator.Emit(OpCodes.Call, typeOfSystemType.GetMethod("GetTypeFromHandle")); ILGenerator.Emit(OpCodes.Ldstr, FieldReference.Name); ILGenerator.EmitPushInteger(Convert.ToInt32(BindingFlags.NonPublic | BindingFlags.Static)); ILGenerator.Emit(OpCodes.Callvirt, typeOfSystemType.GetMethod("GetField", new Type[] { TypeSystem.String, typeof(BindingFlags) })); ILGenerator.EmitStoreLocal(localBuilder); ILGenerator.EmitLoadLocal(localBuilder); ILGenerator.Emit(OpCodes.Ldnull); ILGenerator.Emit(OpCodes.Callvirt, fieldInfoType.GetMethod("GetValue", new Type[] { TypeSystem.Object })); }
private void Visit(DeclareLocalStatement stmt) { var local = IL.DeclareLocal(typeof(BitsValue), "local_" + stmt.Local.Name); Locals.Add(stmt.Local.Name, (local, stmt.Local.BitSize)); if (stmt.Initializer != null) { Visit(stmt.Initializer); IL.Stloc(local); } else { IL.Ldloca(local); IL.Initobj(typeof(BitsValue)); } }
private void EmitPrivateDelegate(MethodInfo methodInfo) { var typeOfDelegate = typeof(Delegate); var localArray = ILGenerator.DeclareLocal(typeof(object[])); var parameters = methodInfo.GetParameters(); Locals.Add(localArray); ILGenerator.Emit(OpCodes.Castclass, typeOfDelegate); ILGenerator.EmitPushInteger(parameters.Length); ILGenerator.Emit(OpCodes.Newarr, TypeSystem.Object); ILGenerator.EmitStoreLocal(localArray); Node.AcceptVisitor(this, ILGenerator); ILGenerator.EmitLoadLocal(localArray); ILGenerator.Emit(OpCodes.Callvirt, typeOfDelegate.GetMethod("DynamicInvoke")); ILGenerator.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType); }
private void EmitPrivate(MethodInfo methodInfo) { Type typeArrayType = typeof(Type[]); Type objectArrayType = typeof(object[]); Type methodInfoType = typeof(MethodInfo); var parameters = methodInfo.GetParameters(); var localTypeArray = ILGenerator.DeclareLocal(typeArrayType); var localObjectArray = ILGenerator.DeclareLocal(objectArrayType); var getTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle"); var invocation = methodInfoType.BaseType.GetMethod("Invoke", new Type[] { TypeSystem.Object, typeof(object[]) }); Locals.Add(localTypeArray); Locals.Add(localObjectArray); ILGenerator.Emit(OpCodes.Ldtoken, methodInfo.DeclaringType); ILGenerator.Emit(OpCodes.Call, getTypeFromHandleMethod); ILGenerator.Emit(OpCodes.Ldstr, methodInfo.Name); ILGenerator.EmitPushInteger(Convert.ToInt32(BindingFlags.NonPublic | BindingFlags.Static)); ILGenerator.Emit(OpCodes.Ldnull); ILGenerator.EmitPushInteger(parameters.Length); ILGenerator.Emit(OpCodes.Newarr, typeArrayType.GetElementType()); ILGenerator.EmitStoreLocal(localTypeArray); parameters.ForEach((p, i) => { ILGenerator.EmitLoadLocal(localTypeArray); ILGenerator.EmitPushInteger(i); ILGenerator.Emit(OpCodes.Ldtoken, p.ParameterType); ILGenerator.Emit(OpCodes.Call, getTypeFromHandleMethod); ILGenerator.Emit(OpCodes.Stelem_Ref); }); ILGenerator.EmitLoadLocal(localTypeArray); ILGenerator.Emit(OpCodes.Ldnull); ILGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetMethod", new Type[] { TypeSystem.String, typeof(BindingFlags), typeof(Binder), typeof(Type[]), typeof(SysReflection.ParameterModifier[]) })); ILGenerator.Emit(OpCodes.Ldnull); ILGenerator.EmitPushInteger(parameters.Length); ILGenerator.Emit(OpCodes.Newarr, TypeSystem.Object); ILGenerator.EmitStoreLocal(localObjectArray); Node.AcceptVisitor(this, ILGenerator); ILGenerator.EmitLoadLocal(localObjectArray); ILGenerator.Emit(OpCodes.Callvirt, invocation); ILGenerator.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType); }
void BuildRoutine([NotNull] ZilRoutine routine, [NotNull] IRoutineBuilder rb, bool entryPoint, bool traceRoutines) { // give the user a chance to rewrite the routine routine = MaybeRewriteRoutine(Context, routine); // set up arguments and locals ClearLocalsAndBlocks(); if (Context.TraceRoutines) { rb.EmitPrint("[" + routine.Name, false); } DefineLocalsFromArgSpec(); if (Context.TraceRoutines) { rb.EmitPrint("]\n", false); } // define a block for the routine Blocks.Clear(); Blocks.Push(new Block { Name = routine.ActivationAtom, AgainLabel = rb.RoutineStart, ReturnLabel = null, Flags = BlockFlags.None }); // generate code for routine body int i = 1; foreach (var stmt in routine.Body) { // only want the result of the last statement // and we never want results in the entry routine, since it can't return CompileStmt(rb, stmt, !entryPoint && i == routine.BodyLength); i++; } // the entry point has to quit instead of returning if (entryPoint) { rb.EmitQuit(); } // clean up WarnAboutUnusedLocals(); ClearLocalsAndBlocks(); // helpers void DefineLocalsFromArgSpec() { foreach (var arg in routine.ArgSpec) { var originalArgName = arg.Atom; var uniqueArgName = MakeUniqueVariableName(originalArgName); if (uniqueArgName != originalArgName) { /* When a parameter has to be renamed because of a conflict, use TempLocalNames * to reserve the new name so we don't collide with it later. For example: * * <GLOBAL FOO <>> * <ROUTINE BLAH (FOO) * <PROG ((FOO)) ...>> * * We rename the local variable to FOO?1 to avoid shadowing the global. * Now the temporary variable bound by the PROG has to be FOO?2. * ZIL code only sees the name FOO: the local is shadowed inside the PROG, * and the global can always be accessed with SETG and GVAL. */ TempLocalNames.Add(uniqueArgName); } var lb = MakeLocalBuilder(arg, uniqueArgName.Text); if (traceRoutines && arg.Type == ArgItem.ArgType.Required) { // TODO: print OPT parameters when tracing routine execution too rb.EmitPrint(" " + originalArgName + "=", false); rb.EmitPrint(PrintOp.Number, lb); } var lbr = new LocalBindingRecord(arg.Type.ToLocalBindingType(), routine.SourceLine, originalArgName.Text, lb); Locals.Add(originalArgName, lbr); AllLocalBindingRecords.Add(lbr); SetOrEmitDefaultValue(lb, arg); } } ILocalBuilder MakeLocalBuilder(ArgItem arg, string uniqueArgName) { ILocalBuilder lb; switch (arg.Type) { case ArgItem.ArgType.Required: try { lb = rb.DefineRequiredParameter(uniqueArgName); } catch (InvalidOperationException) { throw new CompilerError( CompilerMessages.Expression_Needs_Temporary_Variables_Not_Allowed_Here); } break; case ArgItem.ArgType.Optional: lb = rb.DefineOptionalParameter(uniqueArgName); break; case ArgItem.ArgType.Auxiliary: lb = rb.DefineLocal(uniqueArgName); break; default: throw UnhandledCaseException.FromEnum(arg.Type); } return(lb); } void SetOrEmitDefaultValue(ILocalBuilder lb, ArgItem arg) { if (arg.DefaultValue == null) { return; } Debug.Assert(arg.Type == ArgItem.ArgType.Optional || arg.Type == ArgItem.ArgType.Auxiliary); // setting any default value counts as a write MarkVariableAsWritten(lb); lb.DefaultValue = CompileConstant(arg.DefaultValue); if (lb.DefaultValue != null) { return; } ILabel nextLabel = null; // ReSharper disable once SwitchStatementMissingSomeCases switch (arg.Type) { case ArgItem.ArgType.Optional when !rb.HasArgCount: // not a constant throw new CompilerError(routine.SourceLine, CompilerMessages.Optional_Args_With_Nonconstant_Defaults_Not_Supported_For_This_Target); case ArgItem.ArgType.Optional: nextLabel = rb.DefineLabel(); rb.Branch(Condition.ArgProvided, lb, null, nextLabel, true); goto default; default: var val = CompileAsOperand(rb, arg.DefaultValue, routine.SourceLine, lb); if (val != lb) { rb.EmitStore(lb, val); } break; } if (nextLabel != null) { rb.MarkLabel(nextLabel); } } void WarnAboutUnusedLocals() { foreach (var lbr in AllLocalBindingRecords) { if (lbr.IsEverRead || lbr.IsEverWritten) { continue; } if (lbr.Type == LocalBindingType.CompilerTemporary) { continue; } //XXX not sure about this if (lbr.Type == LocalBindingType.RoutineRequired) { continue; } var warning = new CompilerError( lbr.Definition, CompilerMessages.Local_Variable_0_Is_Never_Used, lbr.BoundName); Context.HandleError(warning); } } }
//This is an example of the implementation of the Parse method public override void Parse(TokensStack sTokens) { //We check that the first token is "function" Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } //Now there should be the return type. We pop it from the stack, check for errors, and then set the field Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); //Next is the function name Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; //After the name there should be opening paranthesis for the arguments Token t = sTokens.Pop(); //( if (!(t is Parentheses) || ((Parentheses)t).Name != '(') { throw new SyntaxErrorException($"Expected a '(' but saw '{t}'", t); } //Now we extract the arguments from the stack until we see a closing parathesis while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))//) { //For each argument there should be a type, and a name if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); //If there is a comma, then there is another argument if (sTokens.Count > 0 && sTokens.Peek() is Separator) //, { t = sTokens.Pop(); if (!(t is Separator) || ((Separator)t).Name != ',') { throw new SyntaxErrorException($"Expected a ',' but saw '{t}'", t); } } } //Now we pop out the ) and the {. Note that you need to check that the stack contains the correct symbols here. t = sTokens.Pop();//) if (!(t is Parentheses) || ((Parentheses)t).Name != ')') { throw new SyntaxErrorException($"Expected a ')' but saw '{t}'", t); } t = sTokens.Pop();//{ if (!(t is Parentheses) || ((Parentheses)t).Name != '{') { throw new SyntaxErrorException($"Expected a '{{' but saw '{t}'", t); } //Now we parse the list of local variable declarations while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); //We call the Parse method of the VarDeclaration, which is responsible to parsing the elements of the variable declaration local.Parse(sTokens); Locals.Add(local); } //Now we parse the list of statements while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { //We create the correct Statement type (if, while, return, let) based on the top token in the stack StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); //And call the Parse method of the statement to parse the different parts of the statement s.Parse(sTokens); Body.Add(s); } bool hasReturn = false; if (Body.Count > 0) { StatetmentBase lastStatetment = Body[Body.Count - 1]; Body.RemoveAt(Body.Count - 1); if (lastStatetment is ReturnStatement) { Return = (ReturnStatement)lastStatetment; hasReturn = true; } else { hasReturn = false; } } //Need to check here that the last statement is a return statement //Finally, the function should end with } Token tEnd = sTokens.Pop();//} if (!hasReturn) { throw new SyntaxErrorException("Missing a return statement.", tEnd); } if (!(tEnd is Parentheses) || ((Parentheses)tEnd).Name != '}') { throw new SyntaxErrorException($"Expected a '}}' but saw '{t}'", t); } }
public MethodBodySymbolContext WithLocal(ILocal local) => new MethodBodySymbolContext(SourceSymbolContext, Locals.Add(local), CurrentStatement);
public void CompileExpression(Expression e, bool pop = false, bool addressMode = false, Condition cond = null) { switch (e.ExpressionType) { case ExpressionType.NoOp: break; case ExpressionType.AddressOf: CompileExpression((e as AddressOf).Operand, pop, true); break; case ExpressionType.Constant: { if (cond != null && !cond.Handled) { if ((bool)e.ConstantValue) { cond.CanSkipFalse = true; if (cond.Sequence != ConditionSequence.TrueFollows) { Branch(Opcodes.Br, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); } } else { cond.CanSkipTrue = true; if (cond.Sequence != ConditionSequence.FalseFollows) { Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } } cond.Handled = true; } else if (!pop) { if (e.ConstantValue != null) { Emit(Opcodes.Constant, e.ConstantValue); } else if (!e.ReturnType.IsReferenceType || e.ReturnType.IsGenericType) { Emit(Opcodes.DefaultInit, e.ReturnType); } else { Emit(Opcodes.Null); } if (addressMode) { CreateIndirection(e.ReturnType); } } } break; case ExpressionType.Default: { if (cond != null && !cond.Handled) { Branch(Opcodes.Br, cond.FalseLabel); cond.Handled = true; } else if (!pop) { Emit(Opcodes.DefaultInit, e.ReturnType); if (addressMode) { CreateIndirection(e.ReturnType); } } } break; case ExpressionType.TypeOf: { if (!pop) { Emit(Opcodes.TypeOf, (e as TypeOf).Type); } } break; case ExpressionType.This: { if (pop) { return; } Emit(Opcodes.This); if (!addressMode && Function.DeclaringType.IsValueType) { Emit(Opcodes.LoadObj, Function.DeclaringType); } } break; case ExpressionType.Base: { if (pop) { return; } Emit(Opcodes.This); if (!Function.DeclaringType.IsValueType) { return; } Emit(Opcodes.LoadObj, Function.DeclaringType); Emit(Opcodes.Box, Function.DeclaringType); } break; case ExpressionType.SequenceOp: { var s = e as SequenceOp; CompileExpression(s.Left, !s.Left.ReturnType.IsVoid); CompileExpression(s.Right, pop, addressMode); } break; case ExpressionType.IsOp: { var s = e as IsOp; CompileExpression(s.Operand, pop); if (pop) { break; } if (s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } Emit(Opcodes.AsClass, s.TestType); Emit(Opcodes.Null); Emit(Opcodes.Neq); if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.AsOp: { var s = e as AsOp; CompileExpression(s.Operand, pop); if (pop) { break; } if (s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } Emit(Opcodes.AsClass, s.ReturnType); if (s.ReturnType.IsGenericParameter) { Emit(Opcodes.UnboxAny, s.ReturnType); } if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.LoadLocal: { var s = e as LoadLocal; if (pop) { break; } Emit(addressMode ? Opcodes.LoadLocalAddress : Opcodes.LoadLocal, s.Variable); } break; case ExpressionType.LoadField: { var s = e as LoadField; if (s.Object != null) { CompileExpression(s.Object, false, addressMode && s.Object is This); if (pop) { Pop(); } else { Emit(addressMode ? Opcodes.LoadFieldAddress : Opcodes.LoadField, s.Field); } } else { if (!pop) { Emit(addressMode ? Opcodes.LoadStaticFieldAddress : Opcodes.LoadStaticfield, s.Field); } } } break; case ExpressionType.LoadElement: { var s = e as LoadElement; CompileExpression(s.Array, pop); CompileExpression(s.Index, pop); if (pop) { return; } Emit(addressMode ? Opcodes.LoadArrayElementAddress : Opcodes.LoadArrayElement, s.Array.ReturnType.ElementType); } break; case ExpressionType.LoadArgument: { if (pop) { return; } var s = e as LoadArgument; var paramRef = s.Parameter.IsReference; if (paramRef) { if (addressMode) { Emit(Opcodes.LoadArg, s.Index); } else { Emit(Opcodes.LoadArg, s.Index); Emit(Opcodes.LoadObj, s.Parameter.Type); } } else { Emit(addressMode ? Opcodes.LoadArgAddress : Opcodes.LoadArg, s.Index); } } break; case ExpressionType.StoreLocal: { var s = e as StoreLocal; // TODO: This is a workaround for bug in sub ctor calls, remove this later if (!Locals.Contains(s.Variable)) { Locals.Add(s.Variable); } CompileExpression(s.Value); if (!pop) { Emit(Opcodes.Dup); } Emit(Opcodes.StoreLocal, s.Variable); } break; case ExpressionType.StoreArgument: { var s = e as StoreArgument; if (s.Parameter.IsReference) { Emit(Opcodes.LoadArg, s.Index); // Loads the pointer from a out/ref argument CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreObj, s.Value.ReturnType); LoadTemp(temp); } else { CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreArg, s.Index); LoadTemp(temp); } if (!pop && addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.StoreField: { var s = e as StoreField; if (s.Object != null) { CompileObject(s.Object, s.Field); CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreField, s.Field); LoadTemp(temp); } else { CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreStaticField, s.Field); LoadTemp(temp); } if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.StoreThis: { var s = e as StoreThis; Emit(Opcodes.This); if (!pop & addressMode) { Emit(Opcodes.Dup); } CompileExpression(s.Value); Emit(Opcodes.StoreObj, s.Value.ReturnType); } break; case ExpressionType.StoreElement: { var s = e as StoreElement; CompileExpression(s.Array); CompileExpression(s.Index); CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreArrayElement, s.Value.ReturnType); LoadTemp(temp); if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.SetProperty: { var s = e as SetProperty; CompileObject(s.Object, s.Property); foreach (var arg in s.Arguments) { CompileExpression(arg); } CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Call(s.Object, s.Property.SetMethod); LoadTemp(temp); if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.GetProperty: { var s = e as GetProperty; CompileObject(s.Object, s.Property); foreach (var arg in s.Arguments) { CompileExpression(arg); } if (s.Property.DeclaringType.IsArray && s.Property.Parameters.Length == 0 && s.Property.UnoName == "Length") { Emit(Opcodes.LoadArrayLength); } else { Call(s.Object, s.Property.GetMethod); } if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.AddListener: { var s = e as AddListener; CompileObject(s.Object, s.Event); CompileExpression(s.Listener); Call(s.Object, s.Event.AddMethod); } break; case ExpressionType.RemoveListener: { var s = e as RemoveListener; CompileObject(s.Object, s.Event); CompileExpression(s.Listener); Call(s.Object, s.Event.RemoveMethod); } break; case ExpressionType.ReferenceOp: { var s = e as ReferenceOp; CompileExpression(s.Left); if (s.Left.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Left.ReturnType); } CompileExpression(s.Right); if (s.Right.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Right.ReturnType); } if (cond != null && !cond.Handled) { if (s.EqualityType == EqualityType.NotEqual) { Branch(Opcodes.BrNeq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } else { Branch(Opcodes.BrEq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } cond.Handled = true; return; } Emit(s.EqualityType == EqualityType.NotEqual ? Opcodes.Neq : Opcodes.Eq); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.BranchOp: { var s = e as BranchOp; if (s.BranchType == BranchType.And) { if (cond != null && !cond.Handled) { var brtrue = NewLabel(); CompileCondition(s.Left, ConditionSequence.TrueFollows, brtrue, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); MarkLabel(brtrue); CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); cond.Handled = true; } else { var c = CompileCondition(s.Left, ConditionSequence.TrueFollows); var brafter = NewLabel(); MarkLabel(c.TrueLabel); CompileExpression(s.Right); Branch(Opcodes.Br, brafter); MarkLabel(c.FalseLabel); Emit(Opcodes.Constant, false); MarkLabel(brafter); } } else { if (cond != null && !cond.Handled) { var brfalse = NewLabel(); CompileCondition(s.Left, ConditionSequence.FalseFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), brfalse); MarkLabel(brfalse); CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); cond.Handled = true; } else { var c = CompileCondition(s.Left, ConditionSequence.TrueFollows); var brafter = NewLabel(); MarkLabel(c.TrueLabel); Emit(Opcodes.Constant, true); Branch(Opcodes.Br, brafter); MarkLabel(c.FalseLabel); CompileExpression(s.Right); MarkLabel(brafter); } } } break; case ExpressionType.ConditionalOp: { var s = e as ConditionalOp; var brtrue = NewLabel(); var brfalse = NewLabel(); var brafter = NewLabel(); var cc = CompileCondition(s.Condition, ConditionSequence.TrueFollows, brtrue, brfalse); if (!cc.CanSkipTrue) { MarkLabel(brtrue); CompileExpression(s.True, pop, addressMode); Branch(Opcodes.Br, brafter); } if (!cc.CanSkipFalse) { MarkLabel(brfalse); CompileExpression(s.False, pop, addressMode); } MarkLabel(brafter); } break; case ExpressionType.NullOp: { var s = e as NullOp; var brnull = NewLabel(); var brafter = NewLabel(); CompileExpression(s.Left); Emit(Opcodes.Dup); if (s.Left.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Left.ReturnType); } Branch(Opcodes.BrNotNull, brafter); MarkLabel(brnull); Emit(Opcodes.Pop); CompileExpression(s.Right); MarkLabel(brafter); if (pop) { Pop(); } } break; case ExpressionType.CallCast: { var s = e as CallCast; CompileExpression(s.Operand); // TODO: Many casts are NOOP - i.e. byte -> char, char -> int switch (s.Operand.ReturnType.BuiltinType) { case BuiltinType.Char: case BuiltinType.Byte: case BuiltinType.SByte: case BuiltinType.UShort: case BuiltinType.Short: case BuiltinType.UInt: case BuiltinType.Int: case BuiltinType.ULong: case BuiltinType.Long: case BuiltinType.Float: case BuiltinType.Double: switch (s.ReturnType.BuiltinType) { case BuiltinType.Char: Emit(Opcodes.ConvChar); break; case BuiltinType.Byte: Emit(Opcodes.ConvByte); break; case BuiltinType.SByte: Emit(Opcodes.ConvSByte); break; case BuiltinType.UShort: Emit(Opcodes.ConvUShort); break; case BuiltinType.Short: Emit(Opcodes.ConvShort); break; case BuiltinType.UInt: Emit(Opcodes.ConvUInt); break; case BuiltinType.Int: Emit(Opcodes.ConvInt); break; case BuiltinType.ULong: Emit(Opcodes.ConvULong); break; case BuiltinType.Long: Emit(s.Operand.ReturnType.IsUnsignedType ? Opcodes.ConvULong : Opcodes.ConvLong); break; case BuiltinType.Float: Emit(Opcodes.ConvFloat); break; case BuiltinType.Double: Emit(Opcodes.ConvDouble); break; default: Call(null, s.Cast); break; } break; default: Call(null, s.Cast); break; } if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.CallConstructor: { var s = e as CallConstructor; Emit(Opcodes.This); for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(null, s.Constructor); } break; case ExpressionType.CallMethod: { var s = e as CallMethod; CompileObject(s.Object, s.Method); for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(s.Object, s.Method); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.CallDelegate: { var s = e as CallDelegate; CompileExpression(s.Object); foreach (var arg in s.Arguments) { CompileExpression(arg); } Emit(Opcodes.CallDelegate, s.Object.ReturnType); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.CallBinOp: { CompileBinOp(e as CallBinOp, pop, cond); if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.CallUnOp: { CompileUnOp(e as CallUnOp, pop); if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.CastOp: { var s = e as CastOp; CompileExpression(s.Operand); if (s.ReturnType.IsReferenceType && !s.ReturnType.IsGenericParameter) { if (s.Operand.ReturnType.IsValueType || s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } else { Emit(Opcodes.CastClass, s.ReturnType); } if (pop) { Pop(); } } else if (s.Operand.ReturnType.IsReferenceType && !s.Operand.ReturnType.IsGenericParameter) { if (s.ReturnType.IsValueType) { Emit(Opcodes.Unbox, s.ReturnType); Emit(Opcodes.LoadObj, s.ReturnType); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } else if (s.ReturnType.IsGenericParameter) { Emit(Opcodes.UnboxAny, s.ReturnType); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } else { Emit(Opcodes.CastClass, s.ReturnType); if (pop) { Pop(); } } } else { if (addressMode && !pop) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.NewObject: { var s = e as NewObject; foreach (var arg in s.Arguments) { CompileExpression(arg); } Emit(Opcodes.NewObject, s.Constructor); if (pop) { Pop(); } else if (s.ReturnType.IsValueType && addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.NewDelegate: { var s = e as NewDelegate; if (s.Object != null) { CompileExpression(s.Object); } else { Emit(Opcodes.Null); } if (s.Object == null || s.Object is Base) { Emit(Opcodes.LoadFunction, s.Method); } else { Emit(Opcodes.Dup); Emit(Opcodes.LoadFunctionVirtual, s.Method); } Emit(Opcodes.NewDelegate, s.ReturnType); } break; case ExpressionType.NewArray: { var s = e as NewArray; if (s.Size != null) { CompileExpression(s.Size); } else { Emit(Opcodes.Constant, s.Initializers.Length); } Emit(Opcodes.NewArray, ((RefArrayType)s.ReturnType).ElementType); if (s.Initializers != null) { for (int i = 0; i < s.Initializers.Length; i++) { Emit(Opcodes.Dup); Emit(Opcodes.Constant, i); CompileExpression(s.Initializers[i]); Emit(Opcodes.StoreArrayElement, s.Initializers[i].ReturnType); } } if (pop) { Pop(); } } break; case ExpressionType.FixOp: CompileFixOp(e as FixOp, pop, addressMode); break; case ExpressionType.Swizzle: { var sw = e as Swizzle; CompileExpression(sw.Object); var temp = StoreTemp(sw.Object.ReturnType, false); foreach (var f in sw.Fields) { LoadTemp(temp); Emit(Opcodes.LoadField, f); } Emit(Opcodes.NewObject, sw.Constructor); if (pop) { Pop(); } else if (sw.ReturnType.IsValueType && addressMode) { CreateIndirection(e.ReturnType); } } break; // Shader expression types must be handled to be able to use the bytecode backend for control flow validation of shaders, // as well as generating bytecode/assembly shaders case ExpressionType.RuntimeConst: { var s = e as RuntimeConst; Emit(Opcodes.GetShaderConst, s.State.RuntimeConstants[s.Index]); } break; case ExpressionType.LoadUniform: { var s = e as LoadUniform; Emit(Opcodes.LoadShaderUniform, s.State.Uniforms[s.Index]); } break; case ExpressionType.LoadPixelSampler: { var s = e as LoadPixelSampler; Emit(Opcodes.LoadShaderPixelSampler, s.State.PixelSamplers[s.Index]); } break; case ExpressionType.LoadVarying: { var s = e as LoadVarying; Emit(Opcodes.LoadShaderVarying, s.State.Varyings[s.Index]); } break; case ExpressionType.LoadVertexAttrib: { var s = e as LoadVertexAttrib; Emit(Opcodes.LoadShaderVarying, s.State.VertexAttributes[s.Index]); } break; case ExpressionType.CallShader: { var s = e as CallShader; for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(null, s.Function); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.LoadPtr: { var s = e as LoadPtr; CompileExpression(s.Argument, pop, addressMode, cond); } break; default: throw new Exception("<" + e.ExpressionType + "> is not supported in bytecode backend - at " + e.Source); } }
public Iter(Expression init, Block body) : base(NodeType.Iter, init, body ?? new Block()) { Locals.Add(new Local("$el", null)); }
public Using(Expression init, Block body) : base(NodeType.Using, init, body ?? new Block()) { Locals.Add(new Local("$res", null)); }
/// <summary> /// Compiles the statement, and returns wether or not control flow falls through to the next statement. /// </summary> public void CompileStatement(Statement s, bool markSource) { switch (s.StatementType) { case StatementType.Expression: { var e = s as Expression; var pop = !e.ReturnType.IsVoid; if (markSource) MarkSource(e.Source); CompileExpression(e, pop, false); } break; case StatementType.VariableDeclaration: { var ld = s as VariableDeclaration; for (var var = ld.Variable; var != null; var = var.Next) { Locals.Add(var); if (var.OptionalValue != null) { if (markSource) MarkSource(var.Source); CompileExpression(var.OptionalValue); Emit(Opcodes.StoreLocal, var); } } } break; case StatementType.FixedArrayDeclaration: { var ld = s as FixedArrayDeclaration; Locals.Add(ld.Variable); if (ld.OptionalInitializer != null) { for (int i = 0; i < ld.OptionalInitializer.Length; i++) { if (markSource) MarkSource(ld.OptionalInitializer[i].Source); Emit(Opcodes.Constant, i); CompileExpression(ld.OptionalInitializer[i]); Emit(Opcodes.StoreArrayElement, ld.Variable); } } } break; case StatementType.Scope: { var sc = s as Scope; foreach (var st in sc.Statements) { var scopeCall = st as CallMethod; var markScopeCall = !(scopeCall?.Method != null && scopeCall.Method.IsGenerated); CompileStatement(st, markSource && markScopeCall); } if (sc.Statements.Count == 0 && markSource) MarkSource(sc.Source); } break; case StatementType.While: { var w = s as While; var body = NewLabel(); var cond = NewLabel(); var after = NewLabel(); _breakLabels.Push(after); _continueLabels.Push(cond); if (w.DoWhile) { MarkLabel(body); if (w.OptionalBody != null) CompileStatement(w.OptionalBody, markSource); MarkLabel(cond); if (markSource) MarkSource(w.Condition.Source); CompileCondition(w.Condition, ConditionSequence.FalseFollows, body, after); } else { MarkLabel(cond); if (markSource) MarkSource(w.Condition.Source); CompileCondition(w.Condition, ConditionSequence.TrueFollows, body, after); MarkLabel(body); if (w.OptionalBody != null) CompileStatement(w.OptionalBody, markSource); Branch(Opcodes.Br, cond); } _breakLabels.Pop(); _continueLabels.Pop(); MarkLabel(after); } break; case StatementType.For: { var f = s as For; var body = NewLabel(); var inc = NewLabel(); var cond = NewLabel(); var after = NewLabel(); _breakLabels.Push(after); _continueLabels.Push(inc); if (f.OptionalInitializer != null) CompileStatement(f.OptionalInitializer, markSource); Branch(Opcodes.Br, cond); MarkLabel(body); if (f.OptionalBody != null) CompileStatement(f.OptionalBody, markSource); MarkLabel(inc); if (f.OptionalIncrement != null) { if (markSource) MarkSource(f.OptionalIncrement.Source); CompileExpression(f.OptionalIncrement, true); } MarkLabel(cond); if (f.OptionalCondition != null) { if (markSource) MarkSource(f.OptionalCondition.Source); CompileCondition(f.OptionalCondition, ConditionSequence.FalseFollows, body, after); } else { Branch(Opcodes.Br, body); } _breakLabels.Pop(); _continueLabels.Pop(); MarkLabel(after); } break; case StatementType.IfElse: { var ife = s as IfElse; if (markSource) MarkSource(ife.Condition.Source); var cond = CompileCondition(ife.Condition, ConditionSequence.TrueFollows); MarkLabel(cond.TrueLabel); if (ife.OptionalIfBody != null) CompileStatement(ife.OptionalIfBody, markSource); if (ife.OptionalElseBody != null) { var after = NewLabel(); Branch(Opcodes.Br, after); MarkLabel(cond.FalseLabel); CompileStatement(ife.OptionalElseBody, markSource); MarkLabel(after); } else { MarkLabel(cond.FalseLabel); } } break; case StatementType.Return: { var r = s as Return; if (r.Value != null) { if (markSource) MarkSource(r.Value.Source); CompileExpression(r.Value); Return(r.Value.ReturnType); } else { if (markSource) MarkSource(s.Source); Return(null); } } break; case StatementType.Break: { if (_breakLabels.Count == 0) throw new FatalException(s.Source, ErrorCode.E0015, "Invalid break"); if (markSource) MarkSource(s.Source); Branch(Opcodes.Br, _breakLabels.Peek()); } break; case StatementType.Continue: { if (_continueLabels.Count == 0) throw new FatalException(s.Source, ErrorCode.E0016, "Invalid continue"); if (markSource) MarkSource(s.Source); Branch(Opcodes.Br, _continueLabels.Peek()); } break; case StatementType.TryCatchFinally: { var tc = s as TryCatchFinally; _tryCatchStack.Add(tc); Emit(Opcodes.BeginExceptionBlock); CompileStatement(tc.TryBody, markSource); foreach (var c in tc.CatchBlocks) { Emit(Opcodes.BeginCatchBlock, c.Exception.ValueType); if (markSource) MarkSource(c.Body.Source); Locals.Add(c.Exception); Emit(Opcodes.StoreLocal, c.Exception); CompileStatement(c.Body, markSource); } _tryCatchStack.RemoveLast(); // TODO: finally-clause goes here (_AFTER_ "POP"!) if (tc.OptionalFinallyBody != null) { Emit(Opcodes.BeginFinallyBlock); if (markSource) MarkSource(tc.OptionalFinallyBody.Source); CompileStatement(tc.OptionalFinallyBody, markSource); } Emit(Opcodes.EndExceptionBlock); } break; case StatementType.Switch: { var sw = s as Switch; if (markSource) MarkSource(sw.ControlVariable.Source); CompileExpression(sw.ControlVariable); var temp = StoreTempDontDup(sw.ControlVariable.ReturnType); var after = NewLabel(); Label defaultLabel = null; _breakLabels.Push(after); var caseLabels = new Label[sw.Cases.Length]; for (var i = 0; i < sw.Cases.Length; i++) caseLabels[i] = NewLabel(); for (var i = 0; i < sw.Cases.Length; i++) { for (int v = 0; v < sw.Cases[i].Values.Length; v++) { CompileExpression(sw.Cases[i].Values[v]); LoadTemp(temp); Branch(Opcodes.BrEq, caseLabels[i]); } if (sw.Cases[i].HasDefault) { defaultLabel = caseLabels[i]; } } Branch(Opcodes.Br, defaultLabel ?? after); for (var i = 0; i < sw.Cases.Length; i++) { MarkLabel(caseLabels[i]); CompileStatement(sw.Cases[i].Scope, markSource); Branch(Opcodes.Br, after); } _breakLabels.Pop(); MarkLabel(after); } break; case StatementType.Throw: { var t = s as Throw; if (markSource) MarkSource(t.Source); CompileExpression(t.Exception); Emit(Opcodes.Throw); if (markSource) MarkSource(t.Source); } break; case StatementType.Draw: case StatementType.DrawDispose: break; default: throw new FatalException(s.Source, ErrorCode.I0017, "Statement type not supported in bytecode backend: " + s.StatementType); } }
private Type EmitAssignment(CodeExpression Left, CodeExpression Right, bool ForceTypes) { Depth++; Debug("Emitting assignment expression"); Type Generated = typeof(void); if (Left is CodeVariableReferenceExpression) { // local IL variables generated by parser var Reference = Left as CodeVariableReferenceExpression; LocalBuilder Var; if (Locals.ContainsKey(Reference.VariableName)) { Var = Locals[Reference.VariableName]; } else { Var = Generator.DeclareLocal(typeof(int)); Locals.Add(Reference.VariableName, Var); } EmitExpression(Right, ForceTypes); Generator.Emit(OpCodes.Stloc, Var); Generator.Emit(OpCodes.Pop); } else if (Left is CodeArrayIndexerExpression) { var index = (CodeArrayIndexerExpression)Left; Generator.Emit(OpCodes.Ldloc, VarsProperty); EmitExpression(index.Indices[0]); Type resultType = EmitExpression(Right, ForceTypes); if (resultType.IsValueType) { Generator.Emit(OpCodes.Box, resultType); } Generator.Emit(OpCodes.Callvirt, SetVariable); Generated = typeof(object); } else if (Left is CodePropertyReferenceExpression) { var prop = (CodePropertyReferenceExpression)Left; // HACK: property set method target var info = typeof(Rusty.Core).GetProperty(prop.PropertyName); if (Mirror != null) { info = Mirror.GrabProperty(info); } var set = info == null ? null : info.GetSetMethod(); if (set == null) { Generator.Emit(OpCodes.Ldnull); } else { EmitExpression(Right); Generator.Emit(OpCodes.Dup); Generator.Emit(OpCodes.Call, set); } Generated = typeof(object); } else { throw new CompileException(Left, "Left hand is unassignable"); } Depth--; return(Generated); }
public void AddVariable(string name, object value) { LocalNames.Add(name); Locals.Add(value); }
public override void Parse(TokensStack sTokens) { /* * Function Type ID( args ){ * varDec* * Statments* * Return Statment * } * * check more errors */ Token t; StackIsNotEmpty(sTokens); Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } StackIsNotEmpty(sTokens); Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); StackIsNotEmpty(sTokens); Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "(") { t = sTokens.Pop(); //( } else { throw new SyntaxErrorException("Expected ( Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); if (sTokens.Count > 0 && sTokens.Peek() is Separator)//, { sTokens.Pop(); } } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == ")") { t = sTokens.Pop(); //) } else { throw new SyntaxErrorException("Expected ) Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "{") { t = sTokens.Pop(); //{ } else { throw new SyntaxErrorException("Expected { Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); local.Parse(sTokens); Locals.Add(local); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); s.Parse(sTokens); Body.Add(s); } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "}") { t = sTokens.Pop(); //} } else { throw new SyntaxErrorException("Expected } Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } }