Example #1
0
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            if (TargetType == null)
            {
                throw new Exception("TargetType should be specified before anaylyze is called");
            }

            RType classType = TargetType;
            // TODO It's kinda weird to have resolution here and not in the scope, because similar
            // lookup is done for methods
            while (classType != null && Field == null)
            {
                Field = classType.Fields.FirstOrDefault(f => f.Name == Name);
                if (Field != null)
                {
                    break;
                }

                classType = classType.BaseType;
            }

            if (Field == null)
            {
                var functions = scope.LookupFunction(Name);
                if (functions.Any(f => f.Parameters.IsEmpty()))
                {
                    RppFuncCall funcCall = new RppFuncCall(Name, Collections.NoExprs);
                    return funcCall.Analyze(scope, diagnostic);
                }

                throw SemanticExceptionFactory.ValueIsNotMember(Token, TargetType.ToString());
            }

            Debug.Assert(classType != null, "obj != null");

            Type = new ResolvableType(Field.Type);

            return this;
        }
Example #2
0
        public override void Visit(RppFuncCall node)
        {
            Console.WriteLine("Generating func call");
            // TODO we should keep references to functions by making another pass of code gen before
            // real code generation
            if (node.Name == "ctor()")
            {
                _body.Emit(OpCodes.Ldarg_0);
                ConstructorInfo constructor = typeof(object).GetConstructor(Type.EmptyTypes);
                Debug.Assert(constructor != null, "constructor != null");
                _body.Emit(OpCodes.Call, constructor);
            }
            else
            {
                // TODO Probably makes more sense to make RppConstructorCall ast, instead of boolean
                RppMethodInfo rppMethodInfo = node.Function;
                if (node.IsConstructorCall)
                {
                    _body.Emit(OpCodes.Ldarg_0);
                    node.Args.ForEach(arg => arg.Accept(this));
                    var constructor = rppMethodInfo.Native as ConstructorInfo;
                    _body.Emit(OpCodes.Call, constructor);
                }
                else
                {
                    if (!_inSelector)
                    {
                        if (rppMethodInfo.IsStatic)
                        {
                            var instanceField = rppMethodInfo.DeclaringType.Fields.First(f => f.Name == "_instance");
                            _body.Emit(OpCodes.Ldsfld, instanceField.Native);
                        }
                        else
                        {
                            if (node.IsFromClosure)
                            {
                                _body.Emit(OpCodes.Ldarg_0);
                                Debug.Assert(ClosureContext?.CapturedThis != null, "CapturedThis != null");
                                _body.Emit(OpCodes.Ldfld, ClosureContext.CapturedThis);
                            }
                            else
                            {
                                _body.Emit(OpCodes.Ldarg_0); // load 'this'
                            }
                        }
                    }

                    // Create own code generator for arguments because they can have RppSelectors which may interfer with already existing RppSelector
                    // myField.CallFunc(anotherInstanceFunc()) would set _inSelector to true and no 'this' will be loaded
                    ClrCodegen codegen = new ClrCodegen(_typeBuilder, _body) {ClosureContext = ClosureContext};
                    node.Args.ForEach(arg => arg.Accept(codegen));

                    MethodInfo method = rppMethodInfo.Native as MethodInfo;

                    if (method == null) // This is a stub, so generate code for it
                    {
                        CodegenForStub(rppMethodInfo);
                        return;
                    }

                    Debug.Assert(method != null, "method != null");

                    if (method.IsGenericMethod)
                    {
                        Type[] methodTypeArgs = node.TypeArgs.Select(t => t.Value.NativeType).ToArray();
                        if (methodTypeArgs.Length != 0)
                        {
                            method = method.MakeGenericMethod(methodTypeArgs);
                        }
                    }

                    _body.Emit(OpCodes.Callvirt, method);
                }
            }
        }
Example #3
0
 public override void Visit(RppFuncCall node)
 {
     node.Args.ForEach(arg => arg.Accept(this));
 }
Example #4
0
 public virtual void Visit(RppFuncCall node)
 {
 }