public override void Compile(CompileContext context)
        {
            List<Process> processes = this.Processes;

            for (int i = 0; i < processes.Count; i++) {
                Process p = (Process)processes[i];

                if (context.Options.Optimize && !p.IsUsed) {
                    continue;
                }

                if (p is ProcessConstant && !p.HasRestrictionsOrPreProcess) {
                    //Don't need to create a special proc just for wrapping this
                    ProcessConstant pc = (ProcessConstant)p;
                    EmitRunProcess(context, context.GetType(pc.Name), true, p.LexicalInfo, true);
                } else {
                    string innerTypeName = "NonDeterministic" + (i + 1);
                    TypeInfo newType  = p.CompileNewProcessStart(context, innerTypeName);
                    p.Compile(context);
                    p.CompileNewProcessEnd(context);
                    EmitRunProcess(context, newType, true, p.LexicalInfo, true);
                }
            }
        }
 public override void Compile(CompileContext context)
 {
     foreach (Expression exp in this.Expressions) {
         exp.Compile(context);
         if (exp is ArithmeticExpression) {
             context.ILGenerator.Emit(OpCodes.Box, typeof(Int32));
         }
     }
     context.MarkSequencePoint(this.LexicalInfo);
     EmitRunProcess(context, context.GetType(this.FullName), false, LexicalInfo, false);
 }
        public void Compile(CompileOptions options)
        {
            string absolutePath = Path.Combine(Environment.CurrentDirectory, options.OutputFile);
            string filename = Path.GetFileName(absolutePath);
            string folder = Path.GetDirectoryName(absolutePath);
            AssemblyName name = new AssemblyName(filename);
            AssemblyBuilder assembly = Thread.GetDomain().DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, folder);
            ModuleBuilder module = assembly.DefineDynamicModule(options.OutputFile, filename, options.Debug);
            if (options.EmbedPLR) {
                EmbedAssembly(Assembly.GetExecutingAssembly());
            }

            if (_embeddedAssemblies.Count > 0) {
                GenerateAssemblyLookup(module);
            }

            CompileContext context = new CompileContext();
            context.Options = options;
            context.Module = module;
            MethodBuilder mainMethod = module.DefineGlobalMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { });
            if (options.Debug) {
                context.DebugWriter = module.DefineDocument(options.Arguments[0], Guid.Empty, Guid.Empty, SymDocumentType.Text);
                module.SetUserEntryPoint(mainMethod);
            }

            context.Module = module;
            context.ImportedClasses = _importedClasses;

            if (BeforeCompile != null) {
                BeforeCompile(context);
            }

            foreach (ProcessDefinition procdef in this) {
                procdef.CompileSignature(module, context);
            }

            if (!context.ImportedClasses.Contains(typeof(PLR.Runtime.BuiltIns).FullName)) {
                context.ImportedClasses.Add(typeof(PLR.Runtime.BuiltIns).FullName);
            }
            context.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly());
            if (options.References != "") {

                foreach (string assemblyName in options.References.Split(',')) {
                    string absoluteAssemblyPath = Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
                    if (!File.Exists(absoluteAssemblyPath)) {
                        Console.Error.WriteLine("Assembly '{0}' does not exist!", absoluteAssemblyPath);
                        Environment.Exit(1);
                    }
                    context.ReferencedAssemblies.Add(Assembly.LoadFile(absoluteAssemblyPath));
                }
            }

            foreach (ProcessDefinition procdef in this) {
                context.CurrentMasterType = null;
                procdef.Compile(context);
                context.CurrentMasterType = null;
            }
            List<LocalBuilder> initial = new List<LocalBuilder>();
            context.PushIL(mainMethod.GetILGenerator());
            if (MainMethodStart != null) {
                MainMethodStart(context);
            }
            foreach (ProcessDefinition procdef in this) {
                if (procdef.EntryProc) {
                    TypeInfo startProc = context.GetType(procdef.FullName);
                    LocalBuilder loc = context.ILGenerator.DeclareLocal(startProc.Builder);
                    context.ILGenerator.Emit(OpCodes.Newobj, startProc.Constructor);
                    context.ILGenerator.Emit(OpCodes.Stloc, loc);
                }
            }

            //Run Scheduler, who now knows all the new Processes
            CallScheduler("Run", true, context);

            if (MainMethodEnd!= null) {
                MainMethodEnd(context);
            }

            //return 0;
            context.ILGenerator.Emit(OpCodes.Ldc_I4_0);
            context.ILGenerator.Emit(OpCodes.Ret);

            if (AfterCompile != null) {
                AfterCompile(context);
            }
            module.CreateGlobalFunctions();
            assembly.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
            assembly.Save(filename);
        }
        /// <summary>
        /// Compiles the start block of
        /// </summary>
        /// <param name="context"></param>
        public TypeInfo CompileNewProcessStart(CompileContext context, string name)
        {
            try {
                //Get this before we push a new type on the stack, we are going to need it...
                Dictionary<string, LocalBuilder> currentLocals = null;

                if (context.Type != null) {
                    currentLocals = context.Type.Locals;
                }

                if (context.CurrentMasterType != null) { //Are in a type, so let's create a nested one
                    TypeInfo nestedType = new TypeInfo();
                    nestedType.Builder = context.Type.Builder.DefineNestedType(name, TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.BeforeFieldInit, typeof(ProcessBase));
                    context.PushType(nestedType);
                } else {
                    context.PushType(context.GetType(name));
                    context.CurrentMasterType = context.Type;
                }
                Type baseType = typeof(ProcessBase);

                if (this.PreProcessActions != null) {
                    this.PreProcessActions.Compile(context);
                    context.Type.IsPreProcessed = true;
                }
                if (this.ActionRestrictions != null) {
                    this.ActionRestrictions.Compile(context);
                    context.Type.IsRestricted = true;
                }

                MethodBuilder methodStart = context.Type.Builder.DefineMethod("RunProcess", MethodAttributes.Public | MethodAttributes.Virtual);
                context.Type.Builder.DefineMethodOverride(methodStart, baseType.GetMethod("RunProcess"));
                context.PushIL(methodStart.GetILGenerator());
                Call(new ThisPointer(typeof(ProcessBase)), "InitSetID", true).Compile(context);
                if (this.WrapInTryCatch) {
                    context.ILGenerator.BeginExceptionBlock();
                }

                if (context.Type.Constructor == null) { //Nested type which hasn't defined its constructor yet

                    VariableCollection col = new VariableCollection();
                    col.Start(this);
                    List<Type> paramTypes = new List<Type>();
                    List<Variable> constructorParams = new List<Variable>();
                    foreach (Variable v in col.Variables) {
                        if (currentLocals != null && currentLocals.ContainsKey(v.Name)) { //We have defined this local variable and so should pass it to the new process
                            paramTypes.Add(typeof(object));
                            constructorParams.Add(v);
                            context.Type.ConstructorParameters.Add(v.Name); //Needed to pass the right parameters along later
                            context.Type.Fields.Add(context.Type.Builder.DefineField(v.Name, typeof(object), FieldAttributes.Private));
                        }
                    }
                    context.Type.Constructor = context.Type.Builder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramTypes.ToArray());
                    ILGenerator ilCon = context.Type.Constructor.GetILGenerator();
                    ilCon.Emit(OpCodes.Ldarg_0);
                    ilCon.Emit(OpCodes.Call, typeof(ProcessBase).GetConstructor(new Type[] { }));

                    for (int i = 0; i < constructorParams.Count; i++) {
                        context.Type.Constructor.DefineParameter(i + 1, ParameterAttributes.None, constructorParams[i].Name);
                        //save the variables argument we got passed in
                        ilCon.Emit(OpCodes.Ldarg_0);
                        ilCon.Emit(OpCodes.Ldarg, i + 1);
                        ilCon.Emit(OpCodes.Stfld, context.Type.GetField(constructorParams[i].Name));
                    }
                    ilCon.Emit(OpCodes.Ret);
                }

                //Do this after the constructor has been defined, because the fields
                //of the object are defined in the constructor...
                foreach (FieldBuilder field in context.Type.Fields) {
                    LocalBuilder local = context.ILGenerator.DeclareLocal(typeof(object));
                    if (context.Options.Debug) {
                        local.SetLocalSymInfo(field.Name);
                    }
                    context.Type.Locals.Add(field.Name, local);
                    //Add the field value to the local variable, so we can concentrate on only local vars
                    context.ILGenerator.Emit(OpCodes.Ldarg_0);
                    context.ILGenerator.Emit(OpCodes.Ldfld, field);
                    context.ILGenerator.Emit(OpCodes.Stloc, local);

                }

                return context.Type;
            } catch (Exception) {
                return null;
            }
        }