public static bool Ret(Instruction instruction, CompileContext compileContext)
 {
     // ret - Return from method, possibly with a value.
     if (instruction.Operand != null)
     {
         throw new NotImplementedException();
     }
     compileContext.WriteLine("return;");
     return(true);
 }
        public static bool Br(Instruction instruction, CompileContext compileContext)
        {
            var target = (instruction.Operand as Instruction);

            if (target.OpCode == OpCodes.Ret)
            {
                compileContext.WriteLine("return;");
            }
            else if (target.OpCode == OpCodes.Nop)
            {
            }
            else
            {
                throw new NotImplementedException();
            }
            return(true);
        }
        public static Instruction Step(this Instruction current, Instruction last, CompileContext compileContext)
        {
            if (StatementStructure.Recognize(new CodeBlock(current, last), out StatementStructure statementStructure) != StatementStructureType.Unknown)
            {
                string s = statementStructure.Generate(compileContext);
                compileContext.WriteLine(s);
                return(statementStructure.all.last.Next);
            }
            uint?localVariableIndex = compileContext.GetLocalVariableInstructionIndex(current);

            if (localVariableIndex != null && compileContext.IsUnnecessaryLocalVariableID(localVariableIndex.Value))
            {
                return(current.Next.Next);
            }
            var code = current.OpCode.Code;

            if (!methods.TryGetValue(code, out MethodInfo method))
            {
                throw new Exception(string.Format("Unsupported operate code: {0}", code));
            }
            method.Invoke(null, new object[] { current, compileContext });
            return(current.Next);
        }
        public static bool Call(MethodReference methodReference, CompileContext compileContext)
        {
            var methodDefinition = methodReference.Resolve();

            if (methodDefinition.IsGetter)  // call property getter
            {
                var propertyName       = methodDefinition.Name.Substring("get_".Length);
                var @this              = compileContext.Pop();
                var typeDefinition     = @this.type.Resolve();
                var propertyDefinition = typeDefinition.FindPropertyDefinitionIncludeAncestors(propertyName);
                if (typeof(ScriptableMaterial).IsAssignableFrom(typeDefinition.GetRuntimeType()))
                {
                    Debug.Assert((@this.name as string) == "this");
                    // uniform type is defined as a property in ScriptingMaterial
                    compileContext.Push(propertyDefinition);
                    var propertyInfo = propertyDefinition.DeclaringType.GetRuntimeType().GetProperty(propertyDefinition.Name);
                    if (propertyInfo.GetCustomAttribute <UniformAttribute>() != null)
                    {
                        compileContext.AddUniform(new Uniform(propertyInfo));
                    }
                    else
                    {
                        throw new Exception("uncertain material property get behaviour");
                    }
                    return(true);
                }
                else
                {
                    compileContext.Push(compileContext.Property(@this, propertyDefinition));
                }
            }
            else  // method
            {
                var parameters = compileContext.Pop(methodReference.Parameters.Count());
                if (methodDefinition.IsConstructor)
                {
                    // Call the initializer on the local (from ECMA-335: Page 163)
                    var method = compileContext.Method(methodDefinition, parameters.ToArray());
                    if (compileContext.Peek().isAddress)
                    {
                        var target = compileContext.Pop();
                        compileContext.Assign(target, method);
                    }
                }
                else
                {
                    if (methodDefinition.HasThis)
                    {
                        parameters.Insert(0, compileContext.Pop());
                    }
                    var method = compileContext.Method(methodDefinition, parameters.ToArray());
                    if (!methodDefinition.ReturnType.Resolve().IsSameRuntimeOf(typeof(void).GetTypeDefinition()))
                    {
                        compileContext.Push(method);
                    }
                    else
                    {
                        compileContext.WriteLine(method.ToString());
                    }
                }
            }
            return(true);
        }