/// <summary>Looks for base.new in the given fragment.</summary>
        /// <param name="fragment">The code fragment to look in.</param>
        /// <returns>True if base.new is in this fragment.</returns>
        private bool NewBaseCall(CodeFragment fragment)
        {
            CodeFragment child = fragment.FirstChild;

            while (child != null)
            {
                if (child.GetType() == typeof(MethodFragment))
                {
                    CodeFragment name = ((MethodFragment)child).MethodName;

                    if (name.GetType() == typeof(PropertyFragment) && (((PropertyFragment)name).Value) == "new")
                    {
                        return(true);
                    }
                }
                else if (child.IsParent)
                {
                    if (NewBaseCall(child))
                    {
                        return(true);
                    }
                }

                child = child.NextChild;
            }

            return(false);
        }
Пример #2
0
        /// <summary>Retrieves a section of the reference from the given fragment.
        /// This is required as a reference is likely to be a chain of property fragments which must
        /// be followed to retrieve the full reference.</summary>
        /// <param name="usingName">The current fragment to handle.</param>
        /// <returns>The reference as a string, e.g. 'System.Generics'</returns>
        private string ParseReference(CodeFragment usingName)
        {
            if (usingName == null)
            {
                return("");
            }
            Type type = usingName.GetType();

            if (type == typeof(VariableFragment))
            {
                // e.g. using System;
                return(((VariableFragment)usingName).Value);
            }
            else if (type == typeof(PropertyFragment))
            {
                // e.g. using System.Generic;
                // Follow the stack of 'of' until you hit null.
                PropertyFragment property   = ((PropertyFragment)usingName);
                string           text       = property.Value;
                string           propertyOf = ParseReference(property.of);
                if (propertyOf != "")
                {
                    return(propertyOf + "." + text);
                }
                else
                {
                    return(text);
                }
            }
            return("");
        }
Пример #3
0
        /// <summary>Adds the given fragment as a child of this one.</summary>
        /// <param name="child">The fragment to add as a child.</param>
        public void AddChild(CodeFragment child)
        {
            if(child.GetType()==typeof(OperationFragment) && !child.IsParent){
                // Don't add empty operations
                return;
            }

            child.ParentFragment=this;

            if(FirstChild==null){
                FirstChild=LastChild=child;
            }else{
                child.PreviousChild=LastChild;
                LastChild=LastChild.NextChild=child;
            }
        }
 public override AddResult AddTo(CodeFragment to, CodeLexer sr)
 {
     if (MethodName.GetType() == typeof(VariableFragment))
     {
         VariableFragment vfrag = (VariableFragment)MethodName;
         if (vfrag.Value == "new")
         {
             CodeFragment p = to.LastChild;
             if (p == null || p.GetType() != typeof(VariableFragment) || ((VariableFragment)p).Value != "function")
             {
                 // Constructor call.
                 vfrag.Remove();
                 return(new ConstructorFragment(vfrag.GivenType, Brackets).AddTo(to, sr));
             }
         }
     }
     return(base.AddTo(to, sr));
 }
Пример #5
0
        /// <summary>Globally scopes the given fragment.
        /// This is like stripping the word 'var' from any discovered properties.</summary>
        private void GloballyScope(CodeFragment fragment)
        {
            CodeFragment child = fragment.FirstChild;

            while (child != null)
            {
                if (child.GetType() == typeof(VariableFragment))
                {
                    // It was a variable fragment.
                    VariableFragment variableFragment = child as VariableFragment;

                    // Clear "after var":
                    variableFragment.AfterVar = false;
                }
                else if (child.IsParent)
                {
                    // E.g. this was an OperationFragment. Go into kids:
                    GloballyScope(child);
                }

                child = child.NextChild;
            }
        }
        /// <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();
        }
Пример #7
0
        /// <summary>Finds all classes within the given code fragment, identified with 'class'.</summary>
        /// <param name="frag">The fragment to search.</param>
        private void FindClasses(CodeFragment frag)
        {
            CodeFragment child = frag.FirstChild;

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

                if (child.IsParent)
                {
                    FindClasses(child);
                }
                else if (child.GetType() == typeof(VariableFragment))
                {
                    VariableFragment vfrag = (VariableFragment)child;

                    if (vfrag.Value == "class")
                    {
                        bool isPublic;
                        Modifiers.Handle(vfrag, out isPublic);

                        Type         baseType  = null;
                        CodeFragment nameBlock = vfrag.NextChild;

                        if (nameBlock == null || nameBlock.GetType() != typeof(VariableFragment))
                        {
                            vfrag.Error("Class keyword used but no class name given.");
                        }

                        vfrag.Remove();
                        vfrag = (VariableFragment)nameBlock;

                        if (vfrag.IsKeyword())
                        {
                            vfrag.Error("Can't use keywords for class names.");
                        }

                        string name = vfrag.Value;

                        if (Types.ContainsKey(name))
                        {
                            vfrag.Error("Cannot redefine class " + name + " - it already exists in this scope.");
                        }

                        if (vfrag.GivenType != null)
                        {
                            baseType = vfrag.GivenType.FindType(this);
                        }

                        if (baseType == null)
                        {
                            baseType = typeof(object);
                        }

                        CodeFragment cblock = vfrag.NextChild;

                        if (cblock == null || cblock.GetType() != typeof(BracketFragment))
                        {
                            vfrag.Error("Class " + name + " is missing it's code body. Correct syntax: class " + name + "{ .. }.");
                        }

                        next = cblock.NextChild;
                        vfrag.Remove();
                        cblock.Remove();
                        Types.Add(name, new CompiledClass(cblock, this, name, baseType, isPublic));
                    }
                }

                child = next;
            }
        }
Пример #8
0
		/// <summary>Retrieves a section of the reference from the given fragment.
		/// This is required as a reference is likely to be a chain of property fragments which must
		/// be followed to retrieve the full reference.</summary>
		/// <param name="usingName">The current fragment to handle.</param>
		/// <returns>The reference as a string, e.g. 'System.Generics'</returns>
		private string ParseReference(CodeFragment usingName){
			if(usingName==null){
				return "";
			}
			Type type=usingName.GetType();
			if(type==typeof(VariableFragment)){
				// e.g. using System;
				return ((VariableFragment)usingName).Value;
			}else if(type==typeof(PropertyFragment)){
				// e.g. using System.Generic;
				// Follow the stack of 'of' until you hit null.
				PropertyFragment property=((PropertyFragment)usingName);
				string text=property.Value;
				string propertyOf=ParseReference(property.of);
				if(propertyOf!=""){
					return propertyOf+"."+text;
				}else{
					return text;
				}
			}
			return "";
		}
        public override AddResult AddTo(CodeFragment to, CodeLexer sr)
        {
            if (Value == "")
            {
                return(AddResult.Ok);
            }
            else if (Value == "var")
            {
                // We're reading a local:
                return(AddResult.Local);
            }
            else if (Value == "for" || Value == "while")
            {
                return(new ForFragment(sr, Value).AddTo(to, sr));
            }
            else if (Value == "switch")
            {
                return(new SwitchFragment(sr).AddTo(to, sr));
            }
            else if (Value == "if")
            {
                return(new IfFragment(sr).AddTo(to, sr));
            }
            else if (Value == "else")
            {
                CodeFragment previous = to.ParentFragment;

                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else can only be applied to an if. E.g. if(){}else{}.");
                }

                IfFragment ifFrag = (IfFragment)previous;

                ifFrag.ApplyElseTo.SetIfFalse(new BracketFragment(sr));

                return(AddResult.Stop);
            }
            else if (Value == "elseif")
            {
                CodeFragment previous = to.ParentFragment;
                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else if can only be applied to an if. E.g. if(){}else if{}..");
                }

                IfFragment ifFrag  = (IfFragment)previous;
                IfFragment newfrag = new IfFragment(sr);

                BracketFragment   bf = new BracketFragment();
                OperationFragment op = new OperationFragment();
                op.AddChild(newfrag);
                bf.AddChild(op);

                ifFrag.ApplyElseTo.SetIfFalse(bf);
                ifFrag.ApplyElseTo = newfrag;

                return(AddResult.Stop);
            }
            else
            {
                return(base.AddTo(to, sr));
            }
        }
Пример #10
0
        /// <summary>Finds methods within the given fragment by looking for 'function'.</summary>
        /// <param name="fragment">The fragment to search.</param>
        public void FindMethods(CodeFragment fragment)
        {
            CodeFragment child = fragment.FirstChild;

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

                if (child.IsParent)
                {
                    FindMethods(child);
                }

                try{
                    if (child.GetType() == typeof(VariableFragment))
                    {
                        VariableFragment vfrag    = ((VariableFragment)child);
                        CodeFragment     toRemove = null;
                        string           Value    = vfrag.Value;

                        if (Value == "function")
                        {
                            // Found a function.
                            bool isPublic;
                            Modifiers.Handle(vfrag, out isPublic);

                            // The return type could be on the function word (function:String{return "hey!";})
                            TypeFragment returnType = child.GivenType;

                            toRemove = child;
                            child    = child.NextChild;

                            if (child == null)
                            {
                                fragment.Error("Keyword 'function' can't be used on its own.");
                            }

                            toRemove.Remove();
                            string          name       = "";
                            bool            anonymous  = false;
                            BracketFragment parameters = null;

                            if (child.GetType() == typeof(MethodFragment))
                            {
                                MethodFragment method = (MethodFragment)child;
                                name       = ((VariableFragment)(method.MethodName)).Value;
                                parameters = method.Brackets;
                                toRemove   = child;
                                child      = child.NextChild;
                                toRemove.Remove();
                                returnType = method.GivenType;
                            }
                            else if (child.GetType() == typeof(VariableFragment))
                            {
                                // Found the name
                                vfrag = (VariableFragment)child;

                                if (vfrag.IsKeyword())
                                {
                                    vfrag.Error("Keywords cannot be used as function names (" + vfrag.Value + ").");
                                }

                                name = vfrag.Value;

                                if (returnType == null)
                                {
                                    returnType = child.GivenType;
                                }

                                toRemove = child;
                                child    = child.NextChild;
                                toRemove.Remove();

                                if (child == null)
                                {
                                    fragment.Error("Invalid function definition (" + name + "). All brackets are missing or arent valid.");
                                }
                            }
                            else
                            {
                                anonymous = true;
                            }

                            next = AddFoundMethod(fragment, child, name, anonymous, parameters, returnType, isPublic);
                        }
                    }
                    else if (child.GetType() == typeof(MethodFragment))
                    {
                        // Looking for anonymous methods ( defined as function() )
                        MethodFragment method = (MethodFragment)child;

                        if (method.MethodName.GetType() == typeof(VariableFragment))
                        {
                            VariableFragment methodName = ((VariableFragment)(method.MethodName));
                            string           name       = methodName.Value;

                            if (name == "function")
                            {
                                // Found an anonymous function, function():RETURN_TYPE{}.
                                // Note that function{}; is also possible and is handled above.
                                CodeFragment toRemove = child;
                                child = child.NextChild;
                                toRemove.Remove();

                                next = AddFoundMethod(fragment, child, null, true, method.Brackets, method.GivenType, true);
                            }
                            else if (method.Brackets != null)
                            {
                                FindMethods(method.Brackets);
                            }
                        }
                        else if (method.Brackets != null)
                        {
                            FindMethods(method.Brackets);
                        }
                    }
                }catch (CompilationException e) {
                    if (e.LineNumber == -1 && child != null)
                    {
                        // Setup line number:
                        e.LineNumber = child.GetLineNumber();
                    }

                    // Rethrow:
                    throw e;
                }

                child = next;
            }
        }
Пример #11
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;
            }
        }
Пример #12
0
        /// <summary>Compiles an operation fragment into an executable operation. The fragment may contain multiple
        /// operators and some may even be the same so the furthest right takes priority; 1+2+3 becomes 1+(2+3).
        /// The compiled fragments are placed back into the same operation fragment. When it's complete, the operation
        /// will only contain one compiled fragment.</summary>
        /// <param name="fragment">The operation fragment to compile.</param>
        /// <param name="parentBlock">The method the operations are compiling into.</param>
        public static void CompileOperators(OperationFragment fragment, CompiledMethod parentBlock)
        {
            CodeFragment     child           = fragment.FirstChild;
            OperatorFragment highestPriority = null;

            while (child != null)
            {
                if (child.GetType() == typeof(OperatorFragment))
                {
                    OperatorFragment thisOperator = (OperatorFragment)child;

                    // <= below enforces furthest right:
                    if (highestPriority == null || highestPriority.Value.Priority <= thisOperator.Value.Priority)
                    {
                        highestPriority = thisOperator;
                    }
                }

                child = child.NextChild;
            }

            if (highestPriority == null)
            {
                return;
            }

            CodeFragment left      = highestPriority.PreviousChild;
            CodeFragment right     = highestPriority.NextChild;
            CodeFragment leftUsed  = left;
            CodeFragment rightUsed = right;

            if (left == null || left.GetType() == typeof(OperatorFragment))
            {
                leftUsed = null;
            }
            else if (!Types.IsCompiled(left))
            {
                leftUsed = left.Compile(parentBlock);
            }

            if (right == null || right.GetType() == typeof(OperatorFragment))
            {
                rightUsed = null;
            }
            else if (!Types.IsCompiled(right))
            {
                rightUsed = right.Compile(parentBlock);
            }

            Operation newFragment = highestPriority.Value.ToOperation((CompiledFragment)leftUsed, (CompiledFragment)rightUsed, parentBlock);

            if (newFragment == null)
            {
                highestPriority.Error("Error: An operator has been used but with nothing to use it on! (It was a '" + highestPriority.Value.Pattern + "')");
            }

            // Replace out Left, Right and the operator itself with the new fragment:
            highestPriority.Remove();

            if (left == null)
            {
                newFragment.AddBefore(right);
            }
            else
            {
                newFragment.AddAfter(left);
            }

            if (rightUsed != null)
            {
                right.Remove();
            }

            if (leftUsed != null)
            {
                left.Remove();
            }

            // And call again to collect the rest:
            CompileOperators(fragment, parentBlock);
        }
		/// <summary>Adds the given fragment as a child of this one.</summary>
		/// <param name="child">The fragment to add as a child.</param>
		public void AddChild(CodeFragment child){
			
			if(child.GetType()==typeof(OperationFragment) && !child.IsParent){
				// Don't add empty operations
				return;
			}
			
			child.ParentFragment=this;
			
			if(FirstChild==null){
				FirstChild=LastChild=child;
			}else{
				child.PreviousChild=LastChild;
				LastChild=LastChild.NextChild=child;
			}
			
		}