CodeTypeMember MakeMember(MethodInfo method) { MethodContext methodContext = new MethodContext(this, method); ParameterInfo[] pars = method.GetParameters(); for(int i = 0; i < pars.Length; i++) { ParamContext parContext = new ParamContext(this, pars[i]); if (parContext.IsWrapped) { if (parContext.Direction == FieldDirection.In) { if (pars[i].ParameterType.IsArray) { UnwrapArrayArgument(methodContext, parContext); } else { UnwrapArgument(methodContext, parContext); } } else { UnwrapRefArgument(methodContext, parContext); } } else { PassArgument(methodContext, parContext); } // If last parameter is 'out' and method returns void if (i == pars.Length - 1 && parContext.Direction == FieldDirection.Out && methodContext.RawReturnType == typeof(void)) { // Placeholder for the parameter methodContext.DoBeforeInvoke.Insert(0, new CodeVariableDeclarationStatement(parContext.WrappedType, parContext.Name)); // Remove the parameter methodContext.WrapperParams.RemoveAt(methodContext.WrapperParams.Count - 1); methodContext.WrappedReturnType = parContext.WrappedType; methodContext.DoAfterInvoke.Add( new CodeMethodReturnStatement( new CodeVariableReferenceExpression(parContext.Name))); } } if (methodContext.WrapperParams.Count == 0) { if (methodContext.Name.StartsWith("Is")) { methodContext.CodeMemberMethod = new CodeMemberProperty(); } if (methodContext.Name.StartsWith("Get")) { methodContext.CodeMemberMethod = new CodeMemberProperty(); methodContext.Name = methodContext.Name.Remove(0, 3); } } return methodContext.Emit(); }
void UnwrapRefArgument(MethodContext methodContext, ParamContext parContext) { methodContext.WrapperParams.Add(parContext.ArgDeclaration); CodeVariableDeclarationStatement tmpVariableDeclaration = new CodeVariableDeclarationStatement(parContext.RawType, ((parContext.Direction==FieldDirection.Ref)?"ref":"out") + "_" + parContext.Name); if (parContext.Direction == FieldDirection.Ref) { tmpVariableDeclaration.InitExpression = parContext.UnwrappedArgExpression; } CodeExpression tmpVariableExpression = new CodeVariableReferenceExpression(tmpVariableDeclaration.Name); CodeExpression tmpVariableDirectionalExpression = new CodeDirectionExpression(parContext.Direction, tmpVariableExpression); methodContext.DoBeforeInvoke.Add(tmpVariableDeclaration); methodContext.BaseMethodInvokeParams.Add(tmpVariableDirectionalExpression); CodeAssignStatement assignExpression = new CodeAssignStatement(parContext.ArgRefExpression, Wrap(parContext.RawType, tmpVariableExpression)); methodContext.DoAfterInvoke.Add(assignExpression); }
public ParamContext param() { ParamContext _localctx = new ParamContext(Context, State); EnterRule(_localctx, 4, RULE_param); try { State = 33; ErrorHandler.Sync(this); switch (Interpreter.AdaptivePredict(TokenStream, 3, Context)) { case 1: _localctx = new RefVarContext(_localctx); EnterOuterAlt(_localctx, 1); { State = 31; Match(R_VAR); } break; case 2: _localctx = new ExpContext(_localctx); EnterOuterAlt(_localctx, 2); { State = 32; expr(0); } break; } } catch (RecognitionException re) { _localctx.exception = re; ErrorHandler.ReportError(this, re); ErrorHandler.Recover(this, re); } finally { ExitRule(); } return(_localctx); }
void UnwrapArrayArgument(MethodContext methodContext, ParamContext parContext) { //OUTPUT: // // public void void__array(Test[] arg) // { // Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length]; // for (int i = 0; (i < arg.Length); i = (i + 1)) // { // if ((arg[i] != null)) // { // array_arg[i] = arg[i].WrappedObject; // } // } // this.WrappedObject.void__array(array_arg); // for (int i = 0; (i < arg.Length); i = (i + 1)) // { // if ((array_arg[i] != null)) // { // arg[i] = Test.Wrap(array_arg[i]); // } else // { // arg[i] = null; // } // } // } methodContext.WrapperParams.Add(parContext.ArgDeclaration); string rawArrayName = "array_" + parContext.Name; CodeExpression arg_Length = // arg.Length new CodePropertyReferenceExpression(parContext.ArgRefExpression, "Length"); CodeExpression i = // i new CodeVariableReferenceExpression("i"); CodeStatement loopInit = // int i = 0 new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression(0)); CodeExpression loopCondition = // (i < arg.Length) new CodeBinaryOperatorExpression( i, CodeBinaryOperatorType.LessThan, arg_Length); CodeStatement loopIteration = // i = (i + 1) new CodeAssignStatement( i, new CodeBinaryOperatorExpression( i, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))); CodeExpression arg_i = // arg[i] new CodeIndexerExpression( parContext.ArgRefExpression, i); CodeVariableReferenceExpression array_arg = // array_arg new CodeVariableReferenceExpression(rawArrayName); CodeExpression array_arg_i = // array_arg[i] new CodeIndexerExpression( array_arg, i); // Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length]; methodContext.DoBeforeInvoke.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(parContext.RawType), array_arg.VariableName, new CodeArrayCreateExpression(parContext.RawType, arg_Length))); methodContext.DoBeforeInvoke.Add( new CodeIterationStatement( loopInit, loopCondition, loopIteration, // if new CodeConditionStatement( // (arg[i] != null) new CodeBinaryOperatorExpression( arg_i, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), // array_arg[i] = arg[i].WrappedObject; new CodeAssignStatement( array_arg_i, Unwrap(parContext.RawType, arg_i))))); methodContext.DoAfterInvoke.Add( new CodeIterationStatement( loopInit, loopCondition, loopIteration, // if new CodeConditionStatement( // (array_arg[i] != null) new CodeBinaryOperatorExpression( array_arg_i, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), // new CodeStatement [] { // arg[i] = Test.Wrap(array_arg[i]); new CodeAssignStatement( arg_i, Wrap( parContext.RawType.Assembly.GetType(parContext.RawType.FullName.Replace("[]","")), array_arg_i))}, // else new CodeStatement [] { // arg[i] = null; new CodeAssignStatement( arg_i, new CodePrimitiveExpression(null))}))); methodContext.BaseMethodInvokeParams.Add(array_arg); }
void UnwrapArgument(MethodContext methodContext, ParamContext parContext) { methodContext.WrapperParams.Add(parContext.ArgDeclaration); methodContext.BaseMethodInvokeParams.Add(parContext.UnwrappedDirectionalArgExpression); }
private TypedContext GetContext(IScopeOwner context, int opDepth, int callDepth, int flags) { tokenizer.advance(0); var s0 = tokenizer.peekNext().value; TypedContext ret = null; //number if (int.TryParse(s0, out int unused) && tokenizer.peekNext().value == "." && float.TryParse(tokenizer.peekNext().value, out float num)) { tokenizer.advance(2); s0 += "." + num; } else { tokenizer.advance(0); tokenizer.peekNext(); } //parenthesis if (s0 == "") { tokenizer.advance(0); return(null); } else if (s0 == "(") { if (tokenizer.peekNext().value == ")") { ret = new ParenContext() { parent = context }; tokenizer.advance(1); } else { tokenizer.advance(1); var t1 = GetContext(context, 0, 0, NoBlocks); var sn1 = tokenizer.peekNext().value; if (sn1 == ")" && t1 is TypedContext) { ret = new ParenContext() { parent = context, interior = t1 as TypedContext } } ; else { throw new Exception("yeet"); } } } //blocks and array declaration else if (blockMode == BlockMode.brackets && s0 == "{") { tokenizer.advance(1); var cret = new BlockContext(); while (tokenizer.peekNext().value != "}") { var next = GetContext(context, opDepth, 0, flags); if (next != null) { cret.body.Add(next); } else { throw new Exception("hmm"); } } if (cret.body.Count == 1 && cret.body[0] is SeperatedContext) { tokenizer.advance(0); var aret = new ArrayContext() { parent = context }; aret.content = (cret.body[0] as SeperatedContext)?.children ?? new List <TypedContext>() { cret.body[0] }; aret.type = $"{SysLib.ArrayType.name}<{aret.content[0].type}>"; ret = aret; } else { tokenizer.advance(0); ret = cret; } } //list declaration else if (s0 == "[") { tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); if (tokenizer.peekNext().value != "]") { throw new Exception("Expected one of these: ]"); } var cret = new ListContext(); cret.parent = context; cret.content = (t2 as SeperatedContext)?.children ?? new List <TypedContext>() { t2 }; cret.type = $"{SysLib.ListType.name}<{cret.content[0].type}>"; ret = cret; } //for, while, foreach else if (s0 == "for") { tokenizer.advance(1); var cret = new LoopContext() { parent = context }; var t2 = GetContext(cret, 0, 0, NoBlocks) as ParenContext; if (t2 == null) { throw new Exception("expected a condition for the for loop"); } cret.condition = t2.interior; var t3 = GetContext(cret, 0, 0, 0); cret.body = t3; tokenizer.advance(-1); ret = cret; } else if (s0 == "if") { tokenizer.advance(1); var cret = new IfContext() { parent = context }; var t2 = GetContext(cret, 0, 0, 0) as ParenContext; if (t2 == null || t2.type != SysLib.BoolType.name) { throw new Exception("expected a boolean condition for the if statement"); } cret.condition = t2.interior; var t3 = GetContext(cret, 0, 0, 0); cret.body = t3; // while(tokenizer.peekNext().value == "elif") { // } if (tokenizer.peekNext().value == "else") { tokenizer.advance(1); var eret = new ElseContext() { parent = context, chainParent = cret }; eret.chainParent = cret; var t4 = GetContext(eret, 0, 0, 0); eret.body = t4; ret = eret; } else { ret = cret; } tokenizer.advance(-1); } else if (s0 == "break") { var cret = new BreakContext(); cret.parent = context; cret.type = SysLib.VoidType.name; ret = cret; } //constants else if (int.TryParse(s0, out int i0)) { ret = new ConstContext() { value = i0, type = SysLib.IntType.name } } ; else if (double.TryParse(s0, out double d0)) { ret = new ConstContext() { value = d0, type = SysLib.DoubleType.name } } ; else if (float.TryParse(s0, out float f0)) { ret = new ConstContext() { value = f0, type = SysLib.FloatType.name } } ; else if (long.TryParse(s0, out long l0)) { ret = new ConstContext() { value = l0, type = SysLib.LongType.name } } ; else if (bool.TryParse(s0, out bool b0)) { ret = new ConstContext() { value = b0, type = SysLib.BoolType.name } } ; else if (s0[0] == '"' && s0[s0.Length - 1] == '"') { ret = new ConstContext() { value = s0.Substring(1, s0.Length - 2), type = SysLib.StringType.name } } ; else if (s0.Length == 3 && s0[0] == '\'' && s0[2] == '\'') { ret = new ConstContext() { value = s0[1], type = SysLib.CharType.name } } ; //prefix operators else if (prefixOperators.Contains(s0)) { tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, NoOps); ret = new SimpleOpContext() { a = t2, op = s0 }; tokenizer.advance(-1); } //variables, functions, etc. else { if (ResolveVariable(context, s0, out var match)) { ret = new VarContext() { variable = match } } ; else { if (tokenizer.peekNext().value == ".") { //check imported types //namespace prefixed types string typeName = s0; //reset tokenizer for while loop tokenizer.advance(0); tokenizer.peekNext(); int steps = 0; TypeData td = null; while (!compiler.ValidateType(typeName, out td)) { if (tokenizer.peekNext().value != ".") { break; } typeName += '.' + tokenizer.peekNext().value; steps += 2; } if (td != null) { ret = new StaticTypeContext() { parent = context, type = typeName }; tokenizer.advance(steps); } else { tokenizer.advance(0); } } else { var vc = new VarDecContext() { name = s0 }; context.variables.Add(vc); ret = vc; } } } tokenizer.advance(1); ret.parent = context; //all operators var s1 = tokenizer.peekNext().value; if (flags == NoRecursion) { tokenizer.advance(0); return(ret); } //indexers if ((ret is VarContext || ret is MemberContext) && s1 == "[") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, 0); //get arguments var arguments = t2 is SeperatedContext ? (t2 as SeperatedContext).children : new List <TypedContext>() { t2 }; if (tokenizer.peekNext().value != "]") { throw new Exception("expected one of these: ]"); } if (tokenizer.peekNext().value == "=") { tokenizer.advance(2); var t3 = GetContext(context, 0, callDepth + 1, 0); arguments.Add(t3); var cret = new CallContext() { owner = ret, methodName = "_setIndex", parent = context, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("no indexer for this boi"); } } else { var cret = new CallContext() { owner = ret, methodName = "_getIndex", parent = context, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("no indexer for this boi"); } tokenizer.advance(1); s1 = tokenizer.peekNext().value; } } //array declaration else if (ret is StaticTypeContext && s1 == "[") { tokenizer.advance(1); if (tokenizer.peekNext().value == "]") { ret = new ListContext() { type = $"{SysLib.ListType.name}<{ret.type}>", parent = context }; } else { var t2 = GetContext(context, 0, callDepth + 1, 0); if (t2.type != SysLib.IntType.name) { throw new Exception("array initializer must have an integer length"); } if (tokenizer.peekNext().value != "]") { throw new Exception("expected one of these: ]"); } ret = new ArrayInitContext() { type = $"{SysLib.ArrayType.name}<{ret.type}>", length = t2, parent = context }; } tokenizer.advance(1); } //calls and member accessing, if (s1 == ".") { while (s1 == ".") { var type = ret.type; var memberOrMethod = tokenizer.peekNext().value; if (tokenizer.peekNext().value == "(") { //method tokenizer.advance(2); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion) as ParenContext; if (t2 == null) { throw new Exception("expected arguments"); } //resolve arguments List <TypedContext> arguments = new List <TypedContext>(); if (t2.interior != null) { if (t2.interior is SeperatedContext) { arguments = ((SeperatedContext)t2.interior).children; } else { arguments.Add(t2); } } var cret = new CallContext() { parent = context, owner = ret, methodName = memberOrMethod, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("could not find method"); } tokenizer.advance(0); //if(tokenizer.peekNext().value != ")") throw new Exception("Expected one of these: )"); } else { //member var cret = new MemberContext() { parent = context, owner = ret, memberName = memberOrMethod, }; if (compiler.ValidateMember(cret, out MemberData md)) { tokenizer.advance(2); cret.type = md.returnType; ret = cret; } else { throw new Exception("could not find member"); } } s1 = tokenizer.peekNext().value; } //tokenizer.advance(0); } //Parameter lists else if (s1 == "," && ret is VarDecContext) { var cret = new ParamContext(); var prev = ret as VarDecContext; cret.children.Add(ret); cret.parent = context; while (s1 == ",") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion) as VarDecContext; if (t2 == null) { throw new Exception("excepted parameter"); } if (t2.type == null) { t2.type = prev.type; } prev = t2; cret.children.Add(t2); s1 = tokenizer.peekNext().value; } ret = cret; } //list definition else if (s1 == "," && flags != 4) { var cret = new SeperatedContext(); cret.children.Add(ret); cret.parent = context; while (s1 == ",") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion); cret.children.Add(t2); s1 = tokenizer.peekNext().value; //find common type cret.type = t2.type; } ret = cret; } //assignments if (s1 == "=" && flags != NoOps) { TypedContext variable = ret as VarDecContext ?? (ret as VarContext)?.variable; if (variable == null) { if (ret is MemberContext) { variable = ret; } else { throw new Exception("you can only assign variables"); } } tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); variable.type = t2.type; ret = new AssignContext() { parent = context, variable = ret, value = t2 }; } //from else if (s1 == ":") { var variable = ret as VarDecContext ?? (ret as VarContext).variable; if (variable == null) { throw new Exception("you must get a variable from the following expression"); } tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); var call = new CallContext() { owner = t2, methodName = "_getIter", parent = context }; if (compiler.ValidateCall(call, out MethodData md)) { if (variable.type == null) { variable.type = md.returnType.Between("<", ">"); } } else { throw new Exception("Cannot iterate a type without a _getIter method"); } ret = new FromContext() { parent = context, reference = variable, body = t2 }; } //operators else if (operators.ContainsKey(s1) && flags != NoOps) { tokenizer.advance(1); var t2 = GetContext(context, opDepth + 1, callDepth + 1, flags); var cret = new OpContext() { a = ret, op = s1, b = t2 }; if (t2 is OpContext) { int p0 = operators[s1]; int p1 = operators[((OpContext)t2).op]; if (p0 >= p1) { OpContext deepA = (OpContext)t2; for (; deepA.a is OpContext; deepA = (OpContext)(deepA.a)) { ; } cret.b = deepA.a; deepA.a = cret; cret = (OpContext)t2; } } if (opDepth == 0) { //resolve type ResolveType(cret); } ret = cret; } else { tokenizer.advance(0); } ret.parent = context; return(ret); }
public ExpContext(ParamContext context) { CopyFrom(context); }
public RefVarContext(ParamContext context) { CopyFrom(context); }
public virtual void CopyFrom(ParamContext context) { base.CopyFrom(context); }