예제 #1
0
        /// <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;
        }
예제 #2
0
        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));
        }
 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));
 }
예제 #4
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>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;
		}
예제 #6
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;
            }
        }
예제 #7
0
        /// <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.
                }
            }
        }
예제 #8
0
		/// <summary>Compiles a known keyword fragment into the given method.</summary>
		/// <param name="kwd">The known keyword fragment. return, using, break or continue.</param>
		/// <param name="method">The method to compile the fragment into.</param>
		/// <returns>A compiled instruction of the given keyword.</returns>
		public static CompiledFragment Compile(VariableFragment kwd,CompiledMethod method){
			OperationFragment parent=(OperationFragment)kwd.ParentFragment;
			switch(kwd.Value){
				case "return":
				if(kwd.PreviousChild!=null){
					kwd.Error("Return cannot follow other operations. You might have a missing ;.");
				}
				kwd.Remove();
				ReturnOperation returnOperation=new ReturnOperation(method);
				
				if(parent.FirstChild!=null){
					if((returnOperation.Input0=parent.Compile(method))==null){
						return null;
					}
				}
				
				parent.FirstChild=returnOperation;
				return returnOperation;
				
				case "typeof":
				if(kwd.PreviousChild!=null){
					kwd.Error("Typeof cannot follow other operations. You might have a missing ;.");
				}
				kwd.Remove();
				TypeofOperation tOperation=new TypeofOperation(method);
				
				if(parent.FirstChild==null){
					kwd.Error("typeof command is missing the thing to find the type of.");
				}
				
				if((tOperation.Input0=parent.Compile(method))==null){
					return null;
				}
				
				parent.FirstChild=tOperation;
				return tOperation;
				
				case "using":
				if(kwd.PreviousChild!=null){
					kwd.Error("Using cannot follow other operations. You might be missing a ;.");
				}
				
				kwd.Remove();
				
				if(parent.FirstChild!=null){
					method.Script.AddReference(parent.FirstChild);
				}
				
				return null;
				
				case "break":
				kwd.Remove();
				BreakOperation breakOperation=new BreakOperation(method,1);
				
				if(parent.FirstChild!=null){
					CompiledFragment cf=parent.Compile(method);
					
					if(cf.Value!=null&&cf.Value.GetType()==typeof(int)){
						breakOperation.Depth=(int)cf.Value;
						
						if(breakOperation.Depth<=0){
							parent.Error("Break operations must be greater than 0 loops.");
						}
						
					}else{
						parent.Error("Break statements can only be followed by a fixed integer constant, e.g. break 2; or just break;");
					}
					
				}
				
				parent.FirstChild=breakOperation;
				return breakOperation;
				
				case "continue":
				kwd.Remove();
				ContinueOperation cOperation=new ContinueOperation(method,1);
				
				if(parent.FirstChild!=null){
					CompiledFragment cf=parent.Compile(method);
					
					if(cf.Value!=null&&cf.Value.GetType()==typeof(int)){
						cOperation.Depth=(int)cf.Value;
						if(cOperation.Depth<=0){
							parent.Error("Continue operations must be greater than 0 loops.");
						}
					}else{
						parent.Error("Continue statements can only be followed by a fixed integer constant, e.g. continue 2; or just continue;");
					}
					
				}
				
				parent.FirstChild=cOperation;
				return cOperation;
				
				default:
				parent.Error("Unrecognised keyword: "+kwd.Value);
				return null;
			}
		}
예제 #9
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;
            }
        }
예제 #10
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;
            }
        }
예제 #11
0
        /// <summary>Compiles a known keyword fragment into the given method.</summary>
        /// <param name="kwd">The known keyword fragment. return, using, break or continue.</param>
        /// <param name="method">The method to compile the fragment into.</param>
        /// <returns>A compiled instruction of the given keyword.</returns>
        public static CompiledFragment Compile(VariableFragment kwd, CompiledMethod method)
        {
            OperationFragment parent = (OperationFragment)kwd.ParentFragment;

            switch (kwd.Value)
            {
            case "return":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Return cannot follow other operations. You might have a missing ;.");
                }
                kwd.Remove();
                ReturnOperation returnOperation = new ReturnOperation(method);

                if (parent.FirstChild != null)
                {
                    if ((returnOperation.Input0 = parent.Compile(method)) == null)
                    {
                        return(null);
                    }
                }

                parent.FirstChild = returnOperation;
                return(returnOperation);

            case "typeof":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Typeof cannot follow other operations. You might have a missing ;.");
                }
                kwd.Remove();
                TypeofOperation tOperation = new TypeofOperation(method);

                if (parent.FirstChild == null)
                {
                    kwd.Error("typeof command is missing the thing to find the type of.");
                }

                if ((tOperation.Input0 = parent.Compile(method)) == null)
                {
                    return(null);
                }

                parent.FirstChild = tOperation;
                return(tOperation);

            case "using":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Using cannot follow other operations. You might be missing a ;.");
                }

                kwd.Remove();

                if (parent.FirstChild != null)
                {
                    method.Script.AddReference(parent.FirstChild);
                }

                return(null);

            case "break":
                kwd.Remove();
                BreakOperation breakOperation = new BreakOperation(method, 1);

                if (parent.FirstChild != null)
                {
                    CompiledFragment cf = parent.Compile(method);

                    if (cf.Value != null && cf.Value.GetType() == typeof(int))
                    {
                        breakOperation.Depth = (int)cf.Value;

                        if (breakOperation.Depth <= 0)
                        {
                            parent.Error("Break operations must be greater than 0 loops.");
                        }
                    }
                    else
                    {
                        parent.Error("Break statements can only be followed by a fixed integer constant, e.g. break 2; or just break;");
                    }
                }

                parent.FirstChild = breakOperation;
                return(breakOperation);

            case "continue":
                kwd.Remove();
                ContinueOperation cOperation = new ContinueOperation(method, 1);

                if (parent.FirstChild != null)
                {
                    CompiledFragment cf = parent.Compile(method);

                    if (cf.Value != null && cf.Value.GetType() == typeof(int))
                    {
                        cOperation.Depth = (int)cf.Value;
                        if (cOperation.Depth <= 0)
                        {
                            parent.Error("Continue operations must be greater than 0 loops.");
                        }
                    }
                    else
                    {
                        parent.Error("Continue statements can only be followed by a fixed integer constant, e.g. continue 2; or just continue;");
                    }
                }

                parent.FirstChild = cOperation;
                return(cOperation);

            default:
                parent.Error("Unrecognised keyword: " + kwd.Value);
                return(null);
            }
        }