/// <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); }
/// <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 ArrayFragment(TypeFragment arrayType, BracketFragment defaults) { ArrayType = arrayType; Defaults = defaults; // Add them as children such that code tree iterators can visit them: AddChild(Defaults); }
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 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 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 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 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 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()); } }
/// <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>Adds a method that was found into this classes set of methods to compile.</summary> /// <param name="fragment">The first fragment of the method, used for generating errors. This gives a valid line number.</param> /// <param name="body">The block of code for this method.</param> /// <param name="name">The name of the method. Null if anonymous is true.</param> /// <param name="anonymous">True if this method is an anonymous one and requires a name.</param> /// <param name="parameters">The set of parameters for this method.</param> /// <param name="returnType">The type that this method returns.</param> /// <param name="isPublic">True if this is a public method; false for private.</param> /// <returns>The first fragment following the method, if there is one.</returns> protected virtual CodeFragment AddFoundMethod(CodeFragment fragment, CodeFragment body, string name, bool anonymous, BracketFragment parameters, TypeFragment returnType, bool isPublic) { if (body == null) { fragment.Error("Invalid function definition (" + name + "). The content block {} is missing or isnt valid."); } if (anonymous) { name = "Compiler-Generated-$" + AnonymousCount; AnonymousCount++; } // The following is the explicit code block for this function: BracketFragment codeBlock = (BracketFragment)body; CompiledMethod cMethod = new CompiledMethod(this, name, parameters, codeBlock, returnType, isPublic); MethodOverloads set = MakeOrFind(name, cMethod.Builder.ReturnType); CodeFragment next = body.NextChild; if (anonymous) { CodeFragment newChild = DynamicMethodCompiler.Compile(cMethod, name, set.ReturnType, new ThisOperation(cMethod)); newChild.AddAfter(body); } body.Remove(); set.AddMethod(cMethod); FindMethods(codeBlock); return(next); }
/// <summary>Finds methods within the given fragment by looking for 'function'.</summary> /// <param name="fragment">The fragment to search.</param> public void FindMethods(CodeFragment fragment) { CodeFragment child = fragment.FirstChild; while (child != null) { CodeFragment next = child.NextChild; if (child.IsParent) { FindMethods(child); } try{ if (child.GetType() == typeof(VariableFragment)) { VariableFragment vfrag = ((VariableFragment)child); CodeFragment toRemove = null; string Value = vfrag.Value; if (Value == "function") { // Found a function. bool isPublic; Modifiers.Handle(vfrag, out isPublic); // The return type could be on the function word (function:String{return "hey!";}) TypeFragment returnType = child.GivenType; toRemove = child; child = child.NextChild; if (child == null) { fragment.Error("Keyword 'function' can't be used on its own."); } toRemove.Remove(); string name = ""; bool anonymous = false; BracketFragment parameters = null; if (child.GetType() == typeof(MethodFragment)) { MethodFragment method = (MethodFragment)child; name = ((VariableFragment)(method.MethodName)).Value; parameters = method.Brackets; toRemove = child; child = child.NextChild; toRemove.Remove(); returnType = method.GivenType; } else if (child.GetType() == typeof(VariableFragment)) { // Found the name vfrag = (VariableFragment)child; if (vfrag.IsKeyword()) { vfrag.Error("Keywords cannot be used as function names (" + vfrag.Value + ")."); } name = vfrag.Value; if (returnType == null) { returnType = child.GivenType; } toRemove = child; child = child.NextChild; toRemove.Remove(); if (child == null) { fragment.Error("Invalid function definition (" + name + "). All brackets are missing or arent valid."); } } else { anonymous = true; } next = AddFoundMethod(fragment, child, name, anonymous, parameters, returnType, isPublic); } } else if (child.GetType() == typeof(MethodFragment)) { // Looking for anonymous methods ( defined as function() ) MethodFragment method = (MethodFragment)child; if (method.MethodName.GetType() == typeof(VariableFragment)) { VariableFragment methodName = ((VariableFragment)(method.MethodName)); string name = methodName.Value; if (name == "function") { // Found an anonymous function, function():RETURN_TYPE{}. // Note that function{}; is also possible and is handled above. CodeFragment toRemove = child; child = child.NextChild; toRemove.Remove(); next = AddFoundMethod(fragment, child, null, true, method.Brackets, method.GivenType, true); } else if (method.Brackets != null) { FindMethods(method.Brackets); } } else if (method.Brackets != null) { FindMethods(method.Brackets); } } }catch (CompilationException e) { if (e.LineNumber == -1 && child != null) { // Setup line number: e.LineNumber = child.GetLineNumber(); } // Rethrow: throw e; } child = next; } }