/// <summary>Creates a new index fragment.</summary>
		/// <param name="brackets">The brackets which contain the indices.</param>
		/// <param name="variable">The variable being indexed. This will most commonly be an array.</param>
		public IndexFragment(CodeFragment brackets,CodeFragment variable){
			Brackets=brackets;
			Variable=variable;	
			
			// Add them as children such that code tree iterators can visit them:
			AddChild(Variable);
			AddChild(Brackets);
		}
		/// <summary>Creates a new method call.</summary>
		/// <param name="brackets">The brackets containing the arguments for the method.</param>
		/// <param name="methodName">The name of the method being called.</param>
		public MethodFragment(BracketFragment brackets,CodeFragment methodName){
			Brackets=brackets;
			MethodName=methodName;
			
			// Add them as children such that code tree iterators can visit them:
			AddChild(Brackets);
			
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(to.LastChild==null){
				Error("A property (."+Value+") was found in an unexpected place.");
			}
			// Replace the last child with *THIS*:
			of=to.LastChild;
			of.Remove();
			to.AddChild(this);
			return AddResult.Ok;
		}
		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);
		}
		/// <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;
			}
			
		}
		/// <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;
			}
			
		}
Example #7
0
		/// <summary>Checks if the given code fragment is a CompiledFragment.</summary>
		/// <param name="obj">The fragment to check.</param>
		/// <returns>True if it is a CompiledFragment; false otherwise.</returns>
		public static bool IsCompiled(CodeFragment obj){
			return IsTypeOf(obj,typeof(CompiledFragment));
		}
		/// <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 "";
		}
		/// <summary>Reads a new operation from the given lexer.</summary>
		/// <param name="sr">The lexer to read the operation from.</param>
		/// <param name="parent">The fragment to parent the operation to.</param>
		public OperationFragment(CodeLexer sr,CodeFragment parent){
			ParentFragment=parent;
			LineNumber=sr.LineNumber;
			bool localMode=false;
			
			while(true){
				char peek=sr.Peek();
				
				if(peek==StringReader.NULL){
					return;
				}
				
				if(peek==';'||peek==','){
					// Read it off:
					sr.Read();
					return;
				}
				
				Handler handler=Handlers.Find(peek);
				
				if(handler==Handler.Stop){
					return;
				}
				
				// Handle the fragment:
				CodeFragment fragment;
				
				try{
					
					// Try to get the code fragment:
					fragment=Handlers.Handle(handler,sr);
					
				}catch(CompilationException e){
					
					if(e.LineNumber==-1){
						// Setup line number:
						e.LineNumber=LineNumber;
					}
					
					// Rethrow:
					throw e;
				}
				
				if(localMode){
					
					// Should always be a VariableFragment:
					
					if(fragment.GetType()==typeof(VariableFragment)){
						
						VariableFragment local=(VariableFragment)fragment;
						local.AfterVar=true;
						
					}
					
					localMode=false;
				}
				
				// Try adding the fragment to the operation:
				AddResult status=fragment.AddTo(this,sr);
				
				// What was the outcome?
				switch(status){
					case AddResult.Stop:
						// Halt.
						return;
					case AddResult.Local:
						// Local next:
						localMode=true;
					break;
					// Ok otherwise.
				}
				
			}
		}
		/// <summary>Compiles a set of parameters into an array of compiled fragments.</summary>
		/// <param name="brackets">The parent block which contains each parameter as a child.</param>
		/// <param name="parentBlock">The method the parameters are for.</param>
		/// <returns>A set of compiled fragments.</returns>
		public static CompiledFragment[] CompileParameters(CodeFragment brackets,CompiledMethod parentBlock){
			if(!brackets.IsParent){
				return null;
			}
			
			int count=0;
			brackets.Compile(parentBlock);
			CodeFragment child=brackets.FirstChild;
			CompiledFragment[] output=new CompiledFragment[brackets.ChildCount()];
			
			while(child!=null){
				CompiledFragment frag=(CompiledFragment)child;
				
				if(frag==null){
					return null;
				}
				
				output[count]=frag;
				count++;
				child=child.NextChild;
			}
			
			return output;
		}
		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);
			}
			
		}
Example #12
0
 public CompiledClass(CodeFragment classFragment, NitroCode script, string name, Type baseType, bool isPublic)
 {
     IsPublic = isPublic;
     StartType(name, script, baseType);
     ClassFragment = classFragment;
 }
Example #13
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;
            }
        }
Example #14
0
 /// <summary>Checks if the given code fragment is a CompiledFragment.</summary>
 /// <param name="obj">The fragment to check.</param>
 /// <returns>True if it is a CompiledFragment; false otherwise.</returns>
 public static bool IsCompiled(CodeFragment obj)
 {
     return(IsTypeOf(obj, typeof(CompiledFragment)));
 }
		/// <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;
			
		}
Example #16
0
        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));
            }
        }
		/// <summary>Adds this code fragment as a child before the given one.</summary>
		/// <param name="frag">The fragment to add this before.</param>
		public void AddBefore(CodeFragment frag){
			AddAfter(frag);
			frag.Remove();
			frag.AddAfter(this);
		}
		/// <summary>Adds this code fragment as a child after the given one.</summary>
		/// <param name="frag">The fragment to add this one after.</param>
		public void AddAfter(CodeFragment frag){
			if(frag==null||frag.ParentFragment==null){
				// It's not added to anything anyway.
				return;
			}
			ParentFragment=frag.ParentFragment;
			NextChild=frag.NextChild;
			if(NextChild!=null){
				NextChild.PreviousChild=this;
			}
			frag.NextChild=this;
			PreviousChild=frag;
		}
		/// <summary>Removes this fragment from its parent.</summary>
		public void Remove(){
			if(ParentFragment==null){
				return;
			}
			if(ParentFragment.FirstChild==this){
				ParentFragment.FirstChild=NextChild;
			}
			if(ParentFragment.LastChild==this){
				ParentFragment.LastChild=PreviousChild;
			}
			
			if(NextChild!=null){
				NextChild.PreviousChild=PreviousChild;
			}
			
			if(PreviousChild!=null){
				PreviousChild.NextChild=NextChild;
			}
			
			PreviousChild=NextChild=null;
		}
		/// <summary>Adds a reference which is named in the given fragment. Using name; is handled here.</summary>
		/// <param name="usingName">The fragment containing the reference.</param>
		public void AddReference(CodeFragment usingName){
			string fullName=ParseReference(usingName);
			
			if(References==null){
				References=new List<CodeReference>();
			}
			
			// The fullName value is now e.g. 'System.Generics'
			References.Add(new CodeReference(fullName));
		}
		/// <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;
			}
			
		}
		/// <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;
			}
			
		}
		/// <summary>Adds this fragment as a child to the given fragment.
		/// It may be overriden by some types of fragment as they may wish to handle it differently.</summary>
		/// <param name="to">The parent to add this fragment to.</param>
		/// <param name="sr">The lexer containing the original text code.</param>
		public virtual AddResult AddTo(CodeFragment to,CodeLexer sr){
			to.AddChild(this);
			return AddResult.Ok;
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(Bracket=='['){
				
				if(to.LastChild==null){
					Error("Unexpected indexing. must be something[index].");
				}else{
					CodeFragment var=to.LastChild;
					var.Remove();
					
					return new IndexFragment(this,var).AddTo(to,sr);
				}
				
			}else if(Bracket=='{'&&to.LastChild!=null){
				// new TYPE[]{default,default..};
				
				if(to.LastChild.GetType()==typeof(VariableFragment)&&((VariableFragment)(to.LastChild)).Value=="new"){
					VariableFragment var=(VariableFragment)(to.LastChild);
					
					if(var.GivenType==null){
						Error("new must always be followed by a type name.");
					}else if(!var.GivenType.IsArray){
						Error("new Type{} only works when Type is an array and curley brackets define it's default values e.g. new int[]{1,2}");
					}else{
						var.Remove();
						return new ArrayFragment(var.GivenType,this).AddTo(to,sr);
					}
					
				}
				
			}else if(Bracket=='('&&to.LastChild!=null){
				Type type=to.LastChild.GetType();
				
				if(type==typeof(IndexFragment)||type==typeof(PropertyFragment)||(type==typeof(VariableFragment)&&!((VariableFragment)(to.LastChild)).IsKeyword())){
					// Method call!
					CodeFragment meth=to.LastChild;
					meth.Remove();
					
					return new MethodFragment(this,meth).AddTo(to,sr);
				}
				
			}
			
			return base.AddTo(to,sr);
		}
		/// <summary>Adds this code fragment to the beginning of the given parents child set.</summary>
		/// <param name="parent">The parent to parent this fragment to.</param>
		public void AddToStart(CodeFragment parent){
			if(parent==null){
				return;
			}
			ParentFragment=parent;
			if(parent.FirstChild==null){
				parent.FirstChild=parent.LastChild=this;
			}else{
				NextChild=parent.FirstChild;
				parent.FirstChild=NextChild.PreviousChild=this;
			}
		}
		/// <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;
		}
Example #27
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)
                        {
                            Dom.Log.Add("Warning: Unreachable code detected at line " + child.NextChild.GetLineNumber());
                            child.NextChild = null;
                        }

                        break;
                    }
                }

                child = child.NextChild;
            }

            return(returns);
        }
		/// <summary>Defines a new field on this class.</summary>
		/// <param name="name">The name of the field.</param>
		/// <param name="type">The type of the value held by this field.</param>
		/// <returns>A new FieldBuilder.</returns>
		protected virtual void DefineField(string name,VariableFragment nameFragment,bool isPublic,CodeFragment defaultValue){
			
			Type type=null;
			
			if(nameFragment.GivenType!=null){
				type=nameFragment.GivenType.FindType(Script);
				nameFragment.GivenType=null;
				
				if(type==null){
					nameFragment.Error(name+" has a type that was not recognised.");
				}
				
			}else if(defaultValue!=null){
				
				// Try and compile it:
				CompiledFragment frag=defaultValue.Compile(GetInit());
				
				// Get the output type:
				type=frag.OutputType(out frag);
				
			}
			
			if(type==null){
				nameFragment.Error(name+"'s type isn't given. Should be e.g. "+name+":String if it has no default value.");
			}
			
			FieldBuilder field=Builder.DefineField(name,type,isPublic?FieldAttributes.Public:FieldAttributes.Private);
			Fields[name]=field;
		}
Example #29
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);
        }
		public CompiledClass(CodeFragment classFragment,NitroCode script,string name,Type baseType,bool isPublic){
			IsPublic=isPublic;
			StartType(name,script,baseType);
			ClassFragment=classFragment;
		}
		/// <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;
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			base.AddTo(to,sr);
			return AddResult.Stop;
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(to.LastChild==null||!to.LastChild.Typeable()){
				Error("A type ("+ToString()+") was found in an unexpected place.");
			}
			to.LastChild.GivenType=this;
			return AddResult.Ok;
		}