Beispiel #1
0
        public override void OutputIL(NitroIL into)
        {
            Type type2 = Input1.OutputType(out Input1);

            // Is it something which is being ["indexed"]? May apply to properties too.
            bool indexOperation    = (Input0.GetType() == typeof(IndexOperation));
            bool propertyOperation = (Input0.GetType() == typeof(PropertyOperation));

            if (indexOperation || propertyOperation)
            {
                // Hook up what we will be setting for the index to handle if it needs to.
                // Note that the object will not change as we have already run it's OutputType call above.
                ((Operation)Input0).Input0 = Input1;
            }

            // Update input0 by computing the type it outputs:
            Type type1 = Input0.OutputType(out Input0);

            object value = Input0.ActiveValue();

            if (value.GetType() != typeof(LocalVariable))
            {
                // Local vars can change type so this doesn't affect them.

                if (type1 == null)
                {
                    Error("Can't set to nothing.");
                }

                if (type2 == null)
                {
                    if (type1.IsValueType)
                    {
                        Error("Can't set " + type1 + " to null because it's a value type.");
                    }
                }
                else if (!type1.IsAssignableFrom(type2))
                {
                    Error("Can't implicity convert " + type2 + " to " + type1 + ".");
                }
            }

            if (Types.IsTypeOf(value, typeof(ISettable)))
            {
                ISettable Value = (ISettable)value;

                Value.OutputTarget(into);
                Input1.OutputIL(into);
                Value.OutputSet(into, type2);

                if (Output)
                {
                    // Daisy chaining these sets.
                    Input0.OutputIL(into);
                }
            }
            else if (indexOperation && value.GetType() == typeof(MethodOperation))
            {
                // This is ok! We've called something like obj["hello"]=input1;
                // Just output the method call:
                Input0.OutputIL(into);

                if (Output)
                {
                    Error("Can't daisy chain with an indexer. Place your indexed object furthest left.");
                }
            }
            else if (propertyOperation && value.GetType() == typeof(MethodOperation) && ((MethodOperation)value).MethodName == "set_Item")
            {
                // This is also ok - we've done something like object.property=value; and it mapped to object["property"]=value;
                // Just output the method call:
                Input0.OutputIL(into);

                if (Output)
                {
                    Error("Can't daisy chain with a property set here. Place your indexed object furthest left.");
                }
            }
            else
            {
                Error("Attempted to set to something (a " + value.GetType() + ") that isn't a variable.");
            }
        }
Beispiel #2
0
        /// <summary>Finds properties in the given fragment.</summary>
        /// <param name="fragment">The fragment to search.</param>
        public void FindProperties(CodeFragment fragment)
        {
            CodeFragment child = fragment.FirstChild;
            CodeFragment next  = null;

            while (child != null)
            {
                next = child.NextChild;

                if (child.IsParent)
                {
                    if (child.GetType() == typeof(OperationFragment))
                    {
                        try{
                            // Is it private? Note that if it is, "private" is removed.
                            bool isPublic = !Modifiers.Check(child.FirstChild, "private");

                            // Grab the property name:
                            CodeFragment propName = child.FirstChild;

                            if (propName == null)
                            {
                                child.Error("This value must be followed by something.");
                            }

                            if (propName.GetType() != typeof(VariableFragment))
                            {
                                child.Error("Didn't recognise this as a property. Please note that all code you'd like to run immediately should be inside a function called Start, or in the constructor of a class.");
                            }

                            VariableFragment vfrag = ((VariableFragment)child.FirstChild);

                            // These are never local:
                            vfrag.AfterVar = false;

                            string Name = vfrag.Value;

                            if (vfrag.IsKeyword())
                            {
                                child.Error("Can't use " + Name + " as a property because it's a keyword.");
                            }

                            if (Fields.ContainsKey(Name))
                            {
                                child.Error(Name + " has been defined twice.");
                            }

                            CodeFragment defaultValue = null;

                            if (vfrag.NextChild == null)
                            {
                            }
                            else if (vfrag.NextChild != null && !Types.IsTypeOf(vfrag.NextChild, typeof(OperatorFragment)))
                            {
                                // No type OR default, or the block straight after isn't : or =
                                child.Error(Name + " is missing a type or default value.");
                            }
                            else
                            {
                                OperatorFragment opFrag = (OperatorFragment)vfrag.NextChild;

                                // It must be a set otherwise it's invalid.
                                if (opFrag.Value == null || opFrag.Value.GetType() != typeof(OperatorSet))
                                {
                                    child.Error("Invalid default value provided for '" + Name + "'.");
                                }

                                defaultValue = opFrag.NextChild;
                            }

                            DefineField(Name, vfrag, isPublic, defaultValue);

                            child.Remove();

                            if (defaultValue != null)
                            {
                                GetInit().CodeBlock.AddChild(child);
                            }
                        }catch (CompilationException e) {
                            if (e.LineNumber == -1 && child != null)
                            {
                                // Setup line number:
                                e.LineNumber = child.GetLineNumber();
                            }

                            // Rethrow:
                            throw e;
                        }
                    }
                    else
                    {
                        FindProperties(child);
                    }
                }

                child = next;
            }
        }
Beispiel #3
0
        /// <summary>Loads the parameter block into a set of types.</summary>
        private void ParseParameters()
        {
            if (DefaultParameterValues != null)
            {
                DefaultParameterValues = null;
                Builder.SetParameters(null);
            }

            if (ParameterBlock == null || !ParameterBlock.IsParent)
            {
                // No inputs anyway, e.g. test(){..}
                ParametersOk();
                return;
            }

            // Each of blocks children is an operation segment.

            ParameterTypes         = new Type[ParameterBlock.ChildCount()];
            DefaultParameterValues = new CompiledFragment[ParameterTypes.Length];
            int index = 0;

            // For each parameter..
            CodeFragment current = ParameterBlock.FirstChild;

            while (current != null)
            {
                if (!current.IsParent)
                {
                    Error("Invalid function definition input variable found.");
                }

                // Default value of this variable (if any). E.g. var1=true,var2..
                CompiledFragment DefaultValue = null;

                CodeFragment inputName = current.FirstChild;

                if (inputName.GetType() != typeof(VariableFragment))
                {
                    Error("Invalid function definition inputs for " + Name + ". Must be (var1:type,var2:type[=a default value],var3:type..). [=..] is optional and can be used for any of the variables.");
                }

                string paramName = ((VariableFragment)inputName).Value;

                if (inputName.NextChild == null)
                {
                }
                else if (inputName.NextChild != null && !Types.IsTypeOf(inputName.NextChild, typeof(OperatorFragment)))
                {
                    // No type OR default, or the block straight after isn't : or =
                    Error("Invalid function parameters for " + Name + ". '" + paramName + "' is missing a type or default value.");
                }
                else
                {
                    OperatorFragment opFrag = (OperatorFragment)inputName.NextChild;
                    //it must be a set otherwise it's invalid.

                    if (opFrag.Value == null || opFrag.Value.GetType() != typeof(OperatorSet))
                    {
                        Error("Invalid default function parameter value provided for " + Name + ". '" + paramName + "'.");
                    }

                    current.FirstChild = inputName.NextChild.NextChild;

                    if (!current.IsParent)
                    {
                        Error("Invalid default function definition. Must be (name:type=expr,..)");
                    }

                    DefaultValue = current.Compile(this);
                }

                if (inputName.GivenType != null)
                {
                    ParameterTypes[index] = inputName.GivenType.FindType(Script);
                }
                else if (DefaultValue != null)
                {
                    ParameterTypes[index] = DefaultValue.OutputType(out DefaultValue);
                }
                else
                {
                    Error("Parameter " + paramName + "'s type isn't given. Should be e.g. (" + paramName + ":String,..).");
                }

                DefaultParameterValues[index] = DefaultValue;

                if (ParameterSet.ContainsKey(paramName))
                {
                    Error("Cant use the same parameter name twice. " + paramName + " in function " + Name + ".");
                }
                else if (ParameterTypes[index] == null)
                {
                    Error("Type not given or invalid for parameter " + paramName + " in function " + Name + ".");
                }
                else
                {
                    ParameterSet.Add(paramName, new ParameterVariable(paramName, ParameterTypes[index]));
                }

                current = current.NextChild;
                index++;
            }

            ApplyParameters();
        }
Beispiel #4
0
        public CompiledMethod(CompiledClass parent, string name, BracketFragment parameterBlock, BracketFragment codeBlock, TypeFragment retType, bool isPublic)
        {
            Name           = name;
            Parent         = parent;
            CodeBlock      = codeBlock;
            Script         = Parent.Script;
            ParameterBlock = parameterBlock;

            Type returnType = null;

            if (retType != null)
            {
                returnType = retType.FindType(Script);
                if (returnType == null)
                {
                    Error("Type '" + retType.Value + "' was not found.");
                }
            }
            string           methodName = Name;
            MethodAttributes attrib     = isPublic?MethodAttributes.Public:MethodAttributes.Private;

            if (methodName == "new")
            {
                methodName = ".ctor";
                attrib    |= MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
            }
            // Does the parent base type define this method?
            // If so, use it's name.
            Type baseType = Parent.Builder.BaseType;

            // Parse the parameter set right away:
            ParseParameters();

            MethodInfo mInfo = Types.GetOverload(baseType.GetMethods(), Name, ParameterTypes, true);

            if (mInfo != null)
            {
                methodName = mInfo.Name;
                attrib    |= MethodAttributes.Virtual | MethodAttributes.HideBySig;         //|MethodAttributes.NewSlot;
            }

            bool isVoid = Types.IsVoid(returnType);

            if (isVoid)
            {
                returnType = typeof(void);
            }

            Builder = Parent.Builder.DefineMethod(
                methodName,
                attrib,
                returnType,
                null
                );

            ApplyParameters();

            ILStream    = new NitroIL(Builder.GetILGenerator());
            EndOfMethod = ILStream.DefineLabel();
            if (!isVoid)
            {
                ReturnBay = ILStream.DeclareLocal(returnType);
            }
        }
 /// <summary>Emits the Value held by this compiled fragment if possible.</summary>
 /// <param name="type">The type of the value (or one of the base types of the value).</param>
 /// <param name="into">The IL stream to output the IL into.</param>
 public void EmitValue(Type type, NitroIL into)
 {
     if (type == typeof(string))
     {
         into.Emit(OpCodes.Ldstr, (string)Value);
     }
     else if (type == typeof(int))
     {
         into.Emit(OpCodes.Ldc_I4, (int)Value);
     }
     else if (type == typeof(uint))
     {
         into.Emit(OpCodes.Ldc_I4, (uint)Value);
     }
     else if (type == typeof(long))
     {
         into.Emit(OpCodes.Ldc_I8, (long)Value);
     }
     else if (type == typeof(ulong))
     {
         into.Emit(OpCodes.Ldc_I8, (ulong)Value);
     }
     else if (type == typeof(float))
     {
         into.Emit(OpCodes.Ldc_R4, (float)Value);
     }
     else if (type == typeof(double))
     {
         into.Emit(OpCodes.Ldc_R8, (double)Value);
     }
     else if (type == typeof(OpCode))
     {
         into.Emit((OpCode)Value);
     }
     else if (type == typeof(bool))
     {
         into.Emit(OpCodes.Ldc_I4, ((bool)Value)?1:0);
     }
     else if (type == typeof(short))
     {
         into.Emit(OpCodes.Ldc_I4, (short)Value);
     }
     else if (type == typeof(ushort))
     {
         into.Emit(OpCodes.Ldc_I4, (ushort)Value);
     }
     else if (type == typeof(byte))
     {
         into.Emit(OpCodes.Ldc_I4, (byte)Value);
     }
     else if (type == typeof(sbyte))
     {
         into.Emit(OpCodes.Ldc_I4, (sbyte)Value);
     }
     else if (Types.IsSubclass(Value, typeof(Variable)))
     {
         // Is parent a type of methodoperation or propertyoperation?
         // If it is, IsMemberAccessor is true.
         ((Variable)Value).OutputIL(into, (ParentFragment != null && ParentFragment.IsMemberAccessor()));
     }
     else
     {
         Error("Didn't know how to output value " + Value + " (type is " + type + ")");
     }
 }