/// <summary>Finds which type of fragment will accept and handle the given character.</summary> /// <param name="peek">The character to find a handler for.</param> /// <returns>The handler which will deal with this character. May also be told to stop if no handler is available.</returns> public static Handler Find(char peek) { if (peek == StringReader.NULL || BracketFragment.IsEndBracket(peek) != -1) { return(Handler.Stop); } else if (BracketFragment.WillHandle(peek)) { return(Handler.Brackets); } else if (StringFragment.WillHandle(peek)) { return(Handler.String); } else if (TypeFragment.WillHandle(peek)) { return(Handler.Type); } else if (OperatorFragment.WillHandle(peek)) { return(Handler.Operator); } else if (PropertyFragment.WillHandle(peek)) { return(Handler.Property); } else if (NumberFragment.WillHandle(peek)) { return(Handler.Number); } return(Handler.Variable); }
public void SetIfFalse(BracketFragment ifFalse) { IfFalse = ifFalse; // Add as child such that code tree iterators can visit them: AddChild(IfFalse); }
public SwitchOperation(CompiledMethod method,BracketFragment switching,BracketFragment body):base(method){ Body=body; if(switching.ChildCount()!=1){ switching.Error("Too many entries inside this switches brackets. Should be e.g. switch(name){ .. }"); } // Compile the switching frag: CompiledFragment variableFrag=switching.FirstChild.Compile(method); // Get the active value - this should be a variable object: object activeValue=variableFrag.ActiveValue(); // Try and apply it: Switching=activeValue as Variable; if(Switching==null){ switching.Error("Can only switch variables."); } }
public ObjectFragment(BracketFragment contents) { Contents = contents; // Add them as children such that code tree iterators can visit them: AddChild(Contents); }
/// <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 any other entries in the given code fragment.</summary> /// <param name="fragment">The fragment to search.</param> public void FindOperations(CodeFragment fragment) { CodeFragment child = fragment.FirstChild; CodeFragment next = null; BracketFragment ovrs = null; while (child != null) { next = child.NextChild; if (child.IsParent) { // Got one! // Just gotta transfer it into the method body of OnScriptReady: if (ovrs == null) { ovrs = GetStartMethod().CodeBlock; } // Remove it as a child: child.Remove(); // Remove the word 'var' to ensure its properties are globally scoped. GloballyScope(child); // Add it to start method: ovrs.AddChild(child); } child = next; } }
/// <summary>Creates a new Constructor Fragment.</summary> /// <param name="type">The type of the object to construct.</param> /// <param name="brackets">The arguments for the constructor as a bracket fragment.</param> public ConstructorFragment(TypeFragment type,BracketFragment brackets){ NewType=type; Brackets=brackets; // Add them as children such that code tree iterators can visit them: 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); }
/// <summary>Creates a new Constructor Fragment.</summary> /// <param name="type">The type of the object to construct.</param> /// <param name="brackets">The arguments for the constructor as a bracket fragment.</param> public ConstructorFragment(TypeFragment type, BracketFragment brackets) { NewType = type; Brackets = brackets; // Add them as children such that code tree iterators can visit them: AddChild(Brackets); }
public void SetIfFalse(BracketFragment ifFalse){ IfFalse=ifFalse; // Add as child such that code tree iterators can visit them: AddChild(IfFalse); }
public ArrayFragment(TypeFragment arrayType,BracketFragment defaults){ ArrayType=arrayType; Defaults=defaults; // Add them as children such that code tree iterators can visit them: AddChild(Defaults); }
/// <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 ArrayFragment(TypeFragment arrayType, BracketFragment defaults) { ArrayType = arrayType; Defaults = defaults; // Add them as children such that code tree iterators can visit them: AddChild(Defaults); }
/// <summary>Creates and reads a new for/while loop fragment.</summary> /// <param name="sr">The lexer to read the loop content from.</param> /// <param name="name">This class represents while too. This is the name of the loop; either 'for' or 'while'.</param> public ForFragment(CodeLexer sr, string name) { Value = name; Parameters = new BracketFragment(sr); Body = new BracketFragment(sr); // Add them as children such that code tree iterators can visit them: AddChild(Parameters); AddChild(Body); }
/// <summary>Creates and reads a new if(){} fragment. Note that the else section is not read.</summary> /// <param name="sr">The lexer to read the if condition and its true bracket block from.</param> public IfFragment(CodeLexer sr){ ApplyElseTo=this; Condition=new BracketFragment(sr); IfTrue=new BracketFragment(sr); // Add them as children such that code tree iterators can visit them: AddChild(Condition); AddChild(IfTrue); }
/// <summary>Creates and reads a new if(){} fragment. Note that the else section is not read.</summary> /// <param name="sr">The lexer to read the if condition and its true bracket block from.</param> public IfFragment(CodeLexer sr) { ApplyElseTo = this; Condition = new BracketFragment(sr); IfTrue = new BracketFragment(sr); // Add them as children such that code tree iterators can visit them: AddChild(Condition); AddChild(IfTrue); }
/// <summary>Creates and reads a new for/while loop fragment.</summary> /// <param name="sr">The lexer to read the loop content from.</param> /// <param name="name">This class represents while too. This is the name of the loop; either 'for' or 'while'.</param> public ForFragment(CodeLexer sr,string name){ Value=name; Parameters=new BracketFragment(sr); Body=new BracketFragment(sr); // Add them as children such that code tree iterators can visit them: AddChild(Parameters); AddChild(Body); }
public CompiledMethod(CompiledClass parent,string name,BracketFragment parameterBlock,BracketFragment codeBlock,TypeFragment retType,bool isPublic){ Name=name; Parent=parent; CodeBlock=codeBlock; Script=Parent.Script; ParameterBlock=parameterBlock; Type returnType=null; if(retType!=null){ returnType=retType.FindType(Script); if(returnType==null){ Error("Type '"+retType.Value+"' was not found."); } } string methodName=Name; MethodAttributes attrib=isPublic?MethodAttributes.Public:MethodAttributes.Private; if(methodName=="new"){ methodName=".ctor"; attrib|=MethodAttributes.HideBySig|MethodAttributes.SpecialName|MethodAttributes.RTSpecialName; } // Does the parent base type define this method? // If so, use it's name. Type baseType=Parent.Builder.BaseType; // Parse the parameter set right away: ParseParameters(); MethodInfo mInfo=Types.GetOverload(baseType.GetMethods(),Name,ParameterTypes,true); if(mInfo!=null){ methodName=mInfo.Name; attrib|=MethodAttributes.Virtual|MethodAttributes.HideBySig;//|MethodAttributes.NewSlot; } bool isVoid=Types.IsVoid(returnType); if(isVoid){ returnType=typeof(void); } Builder=Parent.Builder.DefineMethod( methodName, attrib, returnType, null ); ApplyParameters(); ILStream=new NitroIL(Builder.GetILGenerator()); EndOfMethod=ILStream.DefineLabel(); if(!isVoid){ ReturnBay=ILStream.DeclareLocal(returnType); } }
public IfOperation(CompiledMethod method,BracketFragment condition,BracketFragment ifTrue,BracketFragment ifFalse):base(method){ IfTrue=ifTrue; IfFalse=ifFalse; Conditions=CompilationServices.CompileParameters(condition,method); if(Conditions==null||Conditions.Length==0){ Error("An if was defined but with nothing to check (e.g. if(this is empty!){..} )"); } }
/// <summary>Creates a new variable fragment by reading it from the given lexer.</summary> /// <param name="sr">The lexer to read the variable from.</param> public VariableFragment(CodeLexer sr) { Value += char.ToLower(sr.Read()); // Read until some other block can take over: while (true) { char peek = sr.Peek(); if (peek == ';' || peek == ',' || peek == StringReader.NULL || BracketFragment.AnyBracket(peek)) { // Pass control back to the operation: break; } if (sr.PeekJunk()) { // Is Value anything special? if (Value == "var") { break; } else if (Value == "private") { break; } else if (Value == "function") { break; } else if (Value == "class") { break; } else if (Value == "new") { GivenType = new TypeFragment(sr, false); break; } else if (IsKeyword()) { break; } } Handler handle = Handlers.Find(peek); if (handle != Handler.Stop && handle != Handler.Variable && handle != Handler.Number) { break; } Value += char.ToLower(sr.Read()); } }
public IfOperation(CompiledMethod method, BracketFragment condition, BracketFragment ifTrue, BracketFragment ifFalse) : base(method) { IfTrue = ifTrue; IfFalse = ifFalse; Conditions = CompilationServices.CompileParameters(condition, method); if (Conditions == null || Conditions.Length == 0) { Error("An if was defined but with nothing to check (e.g. if(this is empty!){..} )"); } }
public ConstructOperation(TypeFragment type,BracketFragment brackets,CompiledMethod method):base(method){ if(type==null){ Error("A constructor is missing the type to construct. E.g. new myClass();"); } ObjectType=type.FindType(method.Script); if(ObjectType==null){ Error("Couldn't find type '"+type+"'."); } // Compile the brackets - what types to they have? Parameters=CompilationServices.CompileParameters(brackets,method); SetConstructor(); }
public ConstructOperation(TypeFragment type, BracketFragment brackets, CompiledMethod method) : base(method) { if (type == null) { Error("A constructor is missing the type to construct. E.g. new myClass();"); } ObjectType = type.FindType(method.Script); if (ObjectType == null) { Error("Couldn't find type '" + type + "'."); } // Compile the brackets - what types to they have? Parameters = CompilationServices.CompileParameters(brackets, method); SetConstructor(); }
/// <summary>Creates a new type fragment by reading it from the given lexer.</summary> /// <param name="sr">The lexer to read it from.</param> /// <param name="hasColon">True if a colon (:) should be read from the lexer.</param> public TypeFragment(CodeLexer sr, bool hasColon) { HasColon = hasColon; if (HasColon) { // Read off the colon: sr.Read(); } // Read until some other block can take over: while (true) { char peek = sr.Peek(); if (peek == '<') { List <TypeFragment> generics = new List <TypeFragment>(); while (true) { // Read off the < or the comma: sr.Read(); generics.Add(new TypeFragment(sr, false)); if (sr.Peek() == '>') { sr.Read(); GenericSet = generics.ToArray(); break; } } if (sr.Peek() == '[') { SetArray(sr); } break; } else if (peek == '[') { SetArray(sr); break; } else if (peek == ',' || peek == ';' || peek == StringReader.NULL || BracketFragment.AnyBracket(peek) || Operator.IsOperator(peek)) { // Pass control back to the operation: break; } Value += char.ToLower(sr.Read()); } }
public SwitchOperation(CompiledMethod method, BracketFragment switching, BracketFragment body) : base(method) { Body = body; if (switching.ChildCount() != 1) { switching.Error("Too many entries inside this switches brackets. Should be e.g. switch(name){ .. }"); } // Compile the switching frag: CompiledFragment variableFrag = switching.FirstChild.Compile(method); // Get the active value - this should be a variable object: object activeValue = variableFrag.ActiveValue(); // Try and apply it: Switching = activeValue as Variable; if (Switching == null) { switching.Error("Can only switch variables."); } }
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)); } }
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); } }
public ForOperation(CompiledMethod method, BracketFragment rules, BracketFragment body) : base(method) { Body = body; Parameters = CompilationServices.CompileParameters(rules, method); }
/// <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; }
public CompiledMethod(CompiledClass parent, string name, BracketFragment parameterBlock, BracketFragment codeBlock, TypeFragment retType, bool isPublic) { Name = name; Parent = parent; CodeBlock = codeBlock; Script = Parent.Script; ParameterBlock = parameterBlock; Type returnType = null; if (retType != null) { returnType = retType.FindType(Script); if (returnType == null) { Error("Type '" + retType.Value + "' was not found."); } } string methodName = Name; MethodAttributes attrib = isPublic?MethodAttributes.Public:MethodAttributes.Private; if (methodName == "new") { methodName = ".ctor"; attrib |= MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; } // Does the parent base type define this method? // If so, use it's name. Type baseType = Parent.Builder.BaseType; // Parse the parameter set right away: ParseParameters(); MethodInfo mInfo = Types.GetOverload(baseType.GetMethods(), Name, ParameterTypes, true); if (mInfo != null) { methodName = mInfo.Name; attrib |= MethodAttributes.Virtual | MethodAttributes.HideBySig; //|MethodAttributes.NewSlot; } bool isVoid = Types.IsVoid(returnType); if (isVoid) { returnType = typeof(void); } Builder = Parent.Builder.DefineMethod( methodName, attrib, returnType, null ); ApplyParameters(); ILStream = new NitroIL(Builder.GetILGenerator()); EndOfMethod = ILStream.DefineLabel(); if (!isVoid) { ReturnBay = ILStream.DeclareLocal(returnType); } }
/// <summary>Creates and reads a new switch fragment.</summary> /// <param name="sr">The lexer to read the switch content from.</param> public SwitchFragment(CodeLexer sr) { Parameters = new BracketFragment(sr); Body = new BracketFragment(sr); }
public ForOperation(CompiledMethod method,BracketFragment rules,BracketFragment body):base(method){ Body=body; Parameters=CompilationServices.CompileParameters(rules,method); }
/// <summary>Creates and reads a new switch fragment.</summary> /// <param name="sr">The lexer to read the switch content from.</param> public SwitchFragment(CodeLexer sr){ Parameters=new BracketFragment(sr); Body=new BracketFragment(sr); }
/// <summary>Creates a property fragment by reading it from the given lexer.</summary> /// <param name="sr">The lexer to read the fragment from.</param> public PropertyFragment(CodeLexer sr) { // Skip the dot: sr.Read(); // Read a 'variable': Value += char.ToLower(sr.Read()); while (true) { char peek = sr.Peek(); if (peek == ';' || peek == ',' || peek == '.' || peek == StringReader.NULL || BracketFragment.AnyBracket(peek)) { // Pass control back to the operation: break; } Handler handle = Handlers.Find(peek); if (handle != Handler.Stop && handle != Handler.Variable && handle != Handler.Number && handle != Handler.Property) { break; } Value += char.ToLower(sr.Read()); } }
/// <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; } }