예제 #1
0
파일: RppNew.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            // TODO should be unified with RppFuncCall and rethink how types for closures are figureout.
            // we should use constraints and type inference only, not this kind of hacks when we check target
            // closure signature and use types from there

            // Skip closures because they may have missing types
            _arguments = NodeUtils.AnalyzeWithPredicate(scope, _arguments, node => !(node is RppClosure), diagnostic);

            Type.Resolve(scope);

            RType targetType = Type.Value;

            if (NeedToInferGenericArguments(targetType))
            {
                RType inferredTargetType;
                Constructor = FindGenericConstructor(targetType, out inferredTargetType);
                Type = new ResolvableType(inferredTargetType);
            }
            else
            {
                Constructor = FindConstructor(targetType);
            }

            _arguments = RppFuncCall.ReplaceUndefinedClosureTypesIfNeeded(_arguments, Constructor.Parameters, new List<RType>());
            NodeUtils.AnalyzeWithPredicate(scope, _arguments, node => node is RppClosure, diagnostic);

            return this;
        }
예제 #2
0
        public void TestVisitors()
        {
            const string code = @"
class Foo
class Bar extends Foo
object Main
";
            var program = Utils.Parse(code);

            SymbolTable scope = new SymbolTable();
            PopulateBuiltinTypes(scope);

            Type2Creator typeCreator = new Type2Creator();
            program.Accept(typeCreator);
            program.PreAnalyze(scope);
            InheritanceConfigurator2 configurator = new InheritanceConfigurator2();
            program.Accept(configurator);
            var creator = new CreateRType(new Diagnostic());
            program.Accept(creator);
            var classes = program.Classes.Where(c => !c.Name.Contains("Function")).ToArray(); // Remove Functions* from runtime
            var fooType = classes[0].Type;
            var barType = classes[1].Type;
            var mainType = classes[2].Type;

            Assert.IsTrue(fooType.IsClass);
            Assert.IsFalse(fooType.IsAbstract);
            Assert.IsFalse(fooType.IsArray);
            Assert.IsFalse(fooType.IsGenericType);
            Assert.IsFalse(fooType.IsPrimitive);
            Assert.IsFalse(fooType.IsSealed);

            Assert.IsTrue(mainType.IsObject);
        }
예제 #3
0
 /// <summary>
 /// Creates reference to variable and resolves to it's type
 /// </summary>
 public static RppId StaticId(RppVar rppVar)
 {
     RppId classParamInput = Id(rppVar.Name);
     SymbolTable symbolTable = new SymbolTable();
     symbolTable.AddLocalVar(rppVar.Name, rppVar.Type.Value, rppVar);
     classParamInput.Analyze(symbolTable, new Diagnostic());
     return classParamInput;
 }
예제 #4
0
파일: Utils.cs 프로젝트: dubik/csharprpp
        public static Assembly CodeGen(RppProgram program, Diagnostic diagnostic)
        {
            SymbolTable scope = new SymbolTable(null);

            RppTypeSystem.PopulateBuiltinTypes(scope);

            WireRuntime(scope);

            Assembly stdlib = RppCompiler.FindStdlib();
            if (stdlib != null)
            {
                WireAssembly(scope, stdlib);
            }

            CodeGenerator generator = new CodeGenerator(program, "TestAssembly.dll");

            Type2Creator typeCreator = new Type2Creator();
            program.Accept(typeCreator);

            program.PreAnalyze(scope);

            InheritanceConfigurator2 configurator = new InheritanceConfigurator2();
            program.Accept(configurator);

            CreateRType createRType = new CreateRType(diagnostic);
            program.Accept(createRType);

            if (diagnostic.Errors.Any())
            {
                return null;
            }

            SemanticAnalyzerStage1 semanticStage1 = new SemanticAnalyzerStage1(diagnostic);
            program.Accept(semanticStage1);

            program.Analyze(scope, diagnostic);

            if (diagnostic.Errors.Any())
            {
                return null;
            }

            SemanticAnalyzer semantic = new SemanticAnalyzer(diagnostic);
            program.Accept(semantic);

            if (diagnostic.Errors.Any())
            {
                return null;
            }

            InitializeNativeTypes initializeNativeTypes = new InitializeNativeTypes(generator.Module);
            program.Accept(initializeNativeTypes);
            CreateNativeTypes createNativeTypes = new CreateNativeTypes();
            program.Accept(createNativeTypes);

            generator.Generate();
            return generator.Assembly;
        }
예제 #5
0
        public SymbolTable(SymbolTable parent, RType classType, SymbolTable outerScope)
        {
            Parent = parent;
            _classType = classType;
            _outerSymbolTable = outerScope;

            AddGenericParametersToScope(_classType);
            AddNestedToScope(_classType);
        }
예제 #6
0
        public static CodeGenerator Compile(Action<RppProgram> parseFactory, Diagnostic diagnostic, [CanBeNull] Assembly stdlibAssembly,
            string fileName = "<buffer>")
        {
            RppProgram program = new RppProgram();
            SymbolTable runtimeScope = new SymbolTable();

            RppTypeSystem.PopulateBuiltinTypes(runtimeScope);

            WireRuntime(runtimeScope);

            if (stdlibAssembly != null)
            {
                WireAssembly(runtimeScope, stdlibAssembly);
            }

            try
            {
                parseFactory(program);
                CodeGenerator generator = new CodeGenerator(program, fileName);
                Type2Creator typeCreator = new Type2Creator();
                program.Accept(typeCreator);

                program.PreAnalyze(runtimeScope);

                InheritanceConfigurator2 configurator = new InheritanceConfigurator2();
                program.Accept(configurator);

                CreateRType createRType = new CreateRType(diagnostic);
                program.Accept(createRType);

                SemanticAnalyzerStage1 semanticStage1 = new SemanticAnalyzerStage1(diagnostic);
                program.Accept(semanticStage1);

                program.Analyze(runtimeScope, null);

                SemanticAnalyzer semantic = new SemanticAnalyzer(diagnostic);
                program.Accept(semantic);

                InitializeNativeTypes initializeNativeTypes = new InitializeNativeTypes(generator.Module);
                program.Accept(initializeNativeTypes);
                CreateNativeTypes createNativeTypes = new CreateNativeTypes();
                program.Accept(createNativeTypes);

                generator.Generate();
                return generator;
            }
            catch (SemanticException e)
            {
                diagnostic.Error(e.Code, e.Message);
                return null;
            }
            catch (ParserException e)
            {
                diagnostic.Error(e.Code, e.Message);
                return null;
            }
        }
예제 #7
0
파일: RppIf.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            Condition = (IRppExpr) Condition.Analyze(scope, diagnostic);
            ThenExpr = (IRppExpr) ThenExpr.Analyze(scope, diagnostic);
            ElseExpr = (IRppExpr) ElseExpr.Analyze(scope, diagnostic);

            Type = ThenExpr.Type;

            return this;
        }
예제 #8
0
파일: RppThis.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            RType thisType = scope.GetEnclosingType();
            if (thisType == null)
            {
                throw new Exception("Can't find enclosing type for this");
            }

            Type = new ResolvableType(thisType);
            return this;
        }
예제 #9
0
파일: RppWhile.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            Condition = (IRppExpr) Condition.Analyze(scope, diagnostic);
            Body = Body.Analyze(scope, diagnostic);

            if (!Equals(Condition.Type, ResolvableType.BooleanTy))
            {
                throw new Exception("Condition should be boolean not " + Condition.Type);
            }

            return this;
        }
예제 #10
0
파일: RppField.cs 프로젝트: dubik/csharprpp
        public void ResolveType(SymbolTable scope, Diagnostic diagnostic)
        {
            if (Type.IsUndefined())
            {
                // TODO this is not easy to fix because field creates accessors which are functions and they are
                // processed before Analyze, so type of field may not be infered. Solution is to delay accessor synthize
                // to later phases when signatures of all functions are known.
                throw SemanticExceptionFactory.CantInferType(Token);
            }

            Type?.Resolve(scope);
        }
예제 #11
0
        /// <summary>
        /// So we have pattern like this:
        /// case [Pattern] => [Expr]
        /// we need to figure out type of [Expr] but it can depend on variables spawned in
        /// [Pattern], so we need to get thise variables (see RppMatchPattern.DeclareVariables())
        /// and add them to the scope and then anaylize [Expr]
        /// </summary>
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            Pattern = (RppMatchPattern) Pattern.Analyze(scope, diagnostic);

            SymbolTable localScope = new SymbolTable(scope);
            RType inputType = GetInputType(localScope);
            IEnumerable<IRppExpr> locals = Pattern.DeclareVariables(inputType);
            NodeUtils.Analyze(localScope, locals, diagnostic);

            Expr = (IRppExpr) Expr.Analyze(localScope, diagnostic);
            return this;
        }
예제 #12
0
파일: RppVar.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            if (InitExpr is RppEmptyExpr && IsLocalSemantic)
            {
                diagnostic.Error(102, "local variable must be initialized");
                return this;
            }

            // Don't capture variables declared inside closure
            CanBeCaptured = scope.GetEnclosingType()?.Name != RppClosure.TempClosureTypeName;

            // We have 2 cases when type is omited, so we need to get it from initializing expression
            // and when type is specified so we need to resolve it and if there is a closure, propagate that
            // to init expression
            if (Type.IsDefined())
            {
                Type.Resolve(scope);

                InitExpr = TypeInference.ReplaceUndefinedClosureTypesIfNeeded(InitExpr, Type, new List<RType>());
                InitExpr = (IRppExpr) InitExpr.Analyze(scope, diagnostic);
            }
            else
            {
                InitExpr = (IRppExpr) InitExpr.Analyze(scope, diagnostic);
                Type = InitExpr.Type;
            }

            if (IsLocalSemantic)
            {
                scope.AddLocalVar(Name, Type.Value, this);
            }

            if (!(InitExpr is RppEmptyExpr))
            {
                if (ImplicitCast.CanCast(InitExpr.Type.Value, Type.Value))
                {
                    InitExpr = ImplicitCast.CastIfNeeded(InitExpr, Type.Value);
                }
                else
                {
                    throw SemanticExceptionFactory.TypeMismatch(Token, Type.Value.Name, InitExpr.Type.Value.Name);
                }
            }

            return this;
        }
예제 #13
0
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            base.Analyze(scope, diagnostic);

            // Rewrite assignment to function call when assigned to array, e.g. array(index) = value => array.update(index, value)
            if (Left is RppSelector)
            {
                RppSelector selector = (RppSelector) Left;
                if (selector.Path.Name == "apply")
                {
                    RppFuncCall applyFuncCall = selector.Path as RppFuncCall;
                    if (applyFuncCall != null && applyFuncCall.Function.DeclaringType.Name == "Array")
                    {
                        RppSelector updateArray = new RppSelector(selector.Target, new RppFuncCall("update",
                            new List<IRppExpr> {applyFuncCall.Args.First(), Right}));
                        return updateArray.Analyze(scope, diagnostic);
                    }
                }
                else if (selector.Path is RppFieldSelector) // Rewrite assignment to field as a call to setter of the field
                {
                    RppFieldSelector fieldSelector = (RppFieldSelector) selector.Path;
                    return CallSetter(selector.Target, fieldSelector.Field, Right).Analyze(scope, diagnostic);
                }
            }
            else if (Left is RppId)
            {
                RppId id = (RppId) Left;
                if (id.IsField && !id.IsFieldAccessedDirectly)
                {
                    return CallSetter(new RppThis(), id.Field, Right).Analyze(scope, diagnostic);
                }
            }

            if (!Equals(Left.Type, Right.Type))
            {
                if (!Left.Type.Value.IsAssignable(Right.Type.Value))
                {
                    throw SemanticExceptionFactory.TypeMismatch(Right.Token, Left.Type.Value.Name, Right.Type.Value.Name);
                }
            }

            return this;
        }
예제 #14
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;
        }
예제 #15
0
파일: RppMatch.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            Value = (IRppExpr) Value.Analyze(scope, diagnostic);
            RppVar declIn = new RppVar(MutabilityFlag.MfVal, "<in>", Value.Type, Value);
            declIn.Analyze(scope, diagnostic);

            CaseClauses = NodeUtils.Analyze(scope, CaseClauses, diagnostic);

            Type = CheckCommonType(CaseClauses, Token).AsResolvable();
            RppVar declOut = new RppVar(MutabilityFlag.MfVar, "<out>", Type, new RppDefaultExpr(Type));

            RppId declInId = new RppId("<in>", declIn);
            declInId.Analyze(scope, diagnostic);
            RppId declOutId = new RppId("<out>", declOut);

            RppMatchingContext ctx = new RppMatchingContext();
            var ifC = Create(declInId, declOutId, CaseClauses, ctx);
            var expr = new RppBlockExpr(List<IRppNode>(declIn, ifC)) {Exitable = true};

            SymbolTable matchScope = new SymbolTable(scope);
            RppBlockExpr matchBlock = new RppBlockExpr(List<IRppNode>(declOut, expr, declOutId));
            return matchBlock.Analyze(matchScope, diagnostic);
        }
예제 #16
0
        private ResolveResults SearchInFunctions(string name, IEnumerable<IRppExpr> args, SymbolTable scope)
        {
            IReadOnlyCollection<RppMethodInfo> overloads = scope.LookupFunction(name);

            if (overloads.IsEmpty())
            {
                return null;
            }

            DefaultTypesComparator typesComparator = new DefaultTypesComparator(_typeArgs);
            IEnumerable<IRppExpr> argList = args as IList<IRppExpr> ?? args.ToList();
            List<RppMethodInfo> candidates = OverloadQuery.Find(argList, _typeArgs, overloads, typesComparator).ToList();

            if (candidates.Count == 0 && overloads.Any())
            {
                throw SemanticExceptionFactory.CreateOverloadFailureException(_token, candidates, argList, overloads);
            }

            RppMethodInfo candidate = candidates[0];

            IEnumerable<RType> inferredTypeArguments = null;
            if (candidate.GenericParameters != null)
            {
                inferredTypeArguments = InferTypes(candidate, argList).ToList();
            }

            return new ResolveResults(candidate, inferredTypeArguments, scope.IsInsideClosure);
        }
예제 #17
0
파일: Utils.cs 프로젝트: dubik/csharprpp
        private static void WireAssembly(SymbolTable scope, Assembly assembly)
        {
            Type[] types = assembly.GetTypes();

            foreach (Type type in types)
            {
                string name = type.Name;
                if (type.Name.Contains("`"))
                {
                    name = name.Substring(0, name.IndexOf('`'));
                }

                RType rType = RppTypeSystem.GetOrCreateType(name, type);
                scope.AddType(rType);
            }
        }
예제 #18
0
파일: Utils.cs 프로젝트: dubik/csharprpp
        private static void WireRuntime(SymbolTable scope)
        {
            Assembly runtimeAssembly = GetRuntimeAssembly();
            WireAssembly(scope, runtimeAssembly);

            scope.AddType(RppTypeSystem.GetOrCreateType("Exception", typeof(Exception)));
        }
예제 #19
0
파일: RppClass.cs 프로젝트: dubik/csharprpp
 public void ResolveGenericTypeConstraints(SymbolTable scope, Diagnostic diagnostic)
 {
     NodeUtils.Analyze(scope, TypeParams, diagnostic);
 }
예제 #20
0
        private static void WireAssembly(SymbolTable scope, Assembly assembly)
        {
            Type[] types = assembly.GetTypes();

            foreach (Type type in types)
            {
                string name = type.Name;
                if (type.Name.Contains("`"))
                {
                    name = name.Substring(0, name.IndexOf('`'));
                }

                if (type.GetField("_instance", BindingFlags.Public | BindingFlags.Static) != null && !name.EndsWith("$"))
                {
                    name = name + "$";
                }

                RType rType = RppTypeSystem.GetOrCreateType(name, type);
                scope.AddType(rType);
            }
        }
예제 #21
0
        public void OnlyOneInstanceOfTypeIsCreated()
        {
            SymbolTable scope = new SymbolTable();
            PopulateBuiltinTypes(scope);

            RType fooTy = GetOrCreateType("Foo");
            RType otherFooTy = GetOrCreateType("Foo");
            Assert.IsTrue(ReferenceEquals(fooTy, otherFooTy));
        }
예제 #22
0
 public SymbolTable(SymbolTable parent)
 {
     Parent = parent;
 }
예제 #23
0
 public SymbolTable([CanBeNull] SymbolTable parent, [NotNull] RppClosureContext closureContext)
 {
     Parent = parent;
     ClosureContext = closureContext;
 }
예제 #24
0
 public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
 {
     _classes = NodeUtils.Analyze(scope, _classes, diagnostic);
     return this;
 }
예제 #25
0
 public void PreAnalyze(SymbolTable scope)
 {
     _classes.ForEach(c => scope.AddType(c.Type));
     NodeUtils.PreAnalyze(scope, _classes);
 }
예제 #26
0
 public SymbolTable([CanBeNull] SymbolTable parent, [NotNull] RppMethodInfo methodInfo)
 {
     Parent = parent;
     AddGenericParametersToScope(methodInfo);
 }
예제 #27
0
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            _type.Resolve(scope);

            _patterns = NodeUtils.Analyze(scope, _patterns, diagnostic).ToArray();

            TypeSymbol companionObjectSymbol = scope.LookupObject(_type.Name.Name);
            if (companionObjectSymbol != null)
            {
                RppMethodInfo unapplyMethod = FindUnapply(companionObjectSymbol.Type);
                if (unapplyMethod == null)
                {
                    throw new Exception("Can't find unapply method or amount of parameters is wrong");
                }
                _unapplyMethod = unapplyMethod;
            }
            else
            {
                throw new Exception("Can't find companion object!");
            }

            return this;
        }
예제 #28
0
        private static ResolveResults SearchInClosures(string name, IEnumerable<IRppExpr> args, SymbolTable scope)
        {
            RppId closure = new RppId(name);
            Diagnostic diagnostic = new Diagnostic();
            try
            {
                RppMember member = (RppMember) closure.Analyze(scope, diagnostic);
                RType closureType = member.Type.Value;
                if(closureType.IsObject)
                    return null;

                List<RppMethodInfo> applyMethods = closureType.Methods.Where(m => m.Name == "apply").ToList();

                List<RType> argTypes = args.Select(a => a.Type.Value).ToList();
                IEnumerable<RppMethodInfo> candidates = OverloadQuery.Find(argTypes, applyMethods).ToList();

                if (candidates.Count() > 1)
                {
                    throw new Exception("Can't figure out which overload to use");
                }

                if (!candidates.Any())
                {
                    return null;
                }
                return new ClosureResolveResults(member, candidates.First());
            }
            catch (Exception)
            {
                return null;
            }
        }
예제 #29
0
파일: RppClass.cs 프로젝트: dubik/csharprpp
        public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
        {
            Debug.Assert(Scope != null, "Scope != null");

            NodeUtils.Analyze(scope, _nested, diagnostic);

            SymbolTable constructorScope = new SymbolTable(Scope, Type, null);

            _classParams = NodeUtils.Analyze(Scope, _classParams, diagnostic);
            _fields = NodeUtils.Analyze(Scope, _fields, diagnostic);

            _constructors = NodeUtils.Analyze(constructorScope, _constructors, diagnostic);
            _funcs = (List<RppFunc>) NodeUtils.Analyze(Scope, _funcs, diagnostic); // TODO perhaps should be fixed

            return this;
        }
예제 #30
0
        public static ResolveResults ResolveFunction(IToken token, string name, IEnumerable<IRppExpr> args, IEnumerable<RType> typeArgs, SymbolTable scope)
        {
            IEnumerable<IRppExpr> argsList = args as IList<IRppExpr> ?? args.ToList();
            FunctionResolution resolution = new FunctionResolution(token, typeArgs);

            ResolveResults res = resolution.SearchInFunctions(name, argsList, scope);
            if (res != null)
            {
                return res;
            }

            res = SearchInClosures(name, argsList, scope);
            if (res != null)
            {
                return res;
            }

            res = SearchInCompanionObjects(name, argsList, scope);
            return res;
        }