Exemplo n.º 1
0
        /// <summary>Adds a method that was found into this classes set of methods to compile.</summary>
        /// <param name="fragment">The first fragment of the method, used for generating errors. This gives a valid line number.</param>
        /// <param name="body">The block of code for this method.</param>
        /// <param name="name">The name of the method. Null if anonymous is true.</param>
        /// <param name="anonymous">True if this method is an anonymous one and requires a name.</param>
        /// <param name="parameters">The set of parameters for this method.</param>
        /// <param name="returnType">The type that this method returns.</param>
        /// <param name="isPublic">True if this is a public method; false for private.</param>
        /// <returns>The first fragment following the method, if there is one.</returns>
        protected virtual CodeFragment AddFoundMethod(CodeFragment fragment, CodeFragment body, string name, bool anonymous, BracketFragment parameters, TypeFragment returnType, bool isPublic)
        {
            if (body == null)
            {
                fragment.Error("Invalid function definition (" + name + "). The content block {} is missing or isnt valid.");
            }

            if (anonymous)
            {
                name = "Compiler-Generated-$" + AnonymousCount;
                AnonymousCount++;
            }

            // The following is the explicit code block for this function:
            BracketFragment codeBlock = (BracketFragment)body;
            CompiledMethod  cMethod   = new CompiledMethod(this, name, parameters, codeBlock, returnType, isPublic);
            MethodOverloads set       = MakeOrFind(name, cMethod.Builder.ReturnType);
            CodeFragment    next      = body.NextChild;

            if (anonymous)
            {
                CodeFragment newChild = DynamicMethodCompiler.Compile(cMethod, name, set.ReturnType, new ThisOperation(cMethod));
                newChild.AddAfter(body);
            }

            body.Remove();
            set.AddMethod(cMethod);
            FindMethods(codeBlock);

            return(next);
        }
		/// <summary>Adds a method that was found into this classes set of methods to compile.</summary>
		/// <param name="fragment">The first fragment of the method, used for generating errors. This gives a valid line number.</param>
		/// <param name="body">The block of code for this method.</param>
		/// <param name="name">The name of the method. Null if anonymous is true.</param>
		/// <param name="anonymous">True if this method is an anonymous one and requires a name.</param>
		/// <param name="parameters">The set of parameters for this method.</param>
		/// <param name="returnType">The type that this method returns.</param>
		/// <param name="isPublic">True if this is a public method; false for private.</param>
		/// <returns>The first fragment following the method, if there is one.</returns>
		protected virtual CodeFragment AddFoundMethod(CodeFragment fragment,CodeFragment body,string name,bool anonymous,BracketFragment parameters,TypeFragment returnType,bool isPublic){
			
			if(body==null){
				fragment.Error("Invalid function definition ("+name+"). The content block {} is missing or isnt valid.");
			}
			
			if(anonymous){
				name="Compiler-Generated-$"+AnonymousCount;
				AnonymousCount++;
			}
			
			// The following is the explicit code block for this function:
			BracketFragment codeBlock=(BracketFragment)body;
			CompiledMethod cMethod=new CompiledMethod(this,name,parameters,codeBlock,returnType,isPublic);
			MethodOverloads set=MakeOrFind(name,cMethod.Builder.ReturnType);
			CodeFragment next=body.NextChild;
			
			if(anonymous){
				CodeFragment newChild=DynamicMethodCompiler.Compile(cMethod,name,set.ReturnType,new ThisOperation(cMethod));
				newChild.AddAfter(body);
			}
			
			body.Remove();
			set.AddMethod(cMethod);
			FindMethods(codeBlock);
			
			return next;
			
		}
		/// <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;
			}
			
		}
Exemplo n.º 4
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;
            }
        }
Exemplo n.º 5
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;
            }
        }
Exemplo n.º 6
0
        /// <summary>Compiles all operations in a given fragment into executable IL.</summary>
        /// <param name="fragment">The parent fragment. Most likely represents a pair of brackets.</param>
        /// <param name="block">The method that the operations represent.</param>
        /// <returns>True if the block returns something.</returns>
        public static bool CompileOperations(CodeFragment fragment, CompiledMethod block)
        {
            CodeFragment child   = fragment.FirstChild;
            bool         returns = false;

            while (child != null)
            {
                if (Types.IsTypeOf(child, typeof(Operation)))
                {
                    Operation operation = (Operation)child;
                    Type      t         = operation.GetType();

                    try{
                        if (operation.RequiresStoring)
                        {
                            child.Error("Unexpected operation or value - you must give somewhere to hold the result of this.");
                        }

                        // Add the above operation to the block's IL:
                        operation.OutputIL(block.ILStream);
                    }catch (CompilationException e) {
                        // Setup line number:
                        if (e.LineNumber == -1)
                        {
                            e.LineNumber = operation.LineNumber;
                        }

                        // Rethrow:
                        throw e;
                    }


                    if (t == typeof(MethodOperation))
                    {
                        Type returnType = (((MethodOperation)operation).MethodToCall).ReturnType;

                        if (returnType != null && returnType != typeof(void))
                        {
                            // Note this doesn't include (nitro) Void because it's an object as far as .net is concerned!
                            block.ILStream.Emit(OpCodes.Pop);
                        }
                    }

                    returns = (t == typeof(ReturnOperation) || (t == typeof(IfOperation) && ((IfOperation)operation).AllRoutesReturn));

                    if (returns)
                    {
                        if (child.NextChild != null)
                        {
                            Wrench.Log.Add("Warning: Unreachable code detected at line " + child.NextChild.GetLineNumber());
                            child.NextChild = null;
                        }

                        break;
                    }
                }

                child = child.NextChild;
            }

            return(returns);
        }