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; }
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); }
/// <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; }
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; }
public SymbolTable(SymbolTable parent, RType classType, SymbolTable outerScope) { Parent = parent; _classType = classType; _outerSymbolTable = outerScope; AddGenericParametersToScope(_classType); AddNestedToScope(_classType); }
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; } }
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; }
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; }
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; }
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); }
/// <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; }
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; }
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; }
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; }
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); }
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); }
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); } }
private static void WireRuntime(SymbolTable scope) { Assembly runtimeAssembly = GetRuntimeAssembly(); WireAssembly(scope, runtimeAssembly); scope.AddType(RppTypeSystem.GetOrCreateType("Exception", typeof(Exception))); }
public void ResolveGenericTypeConstraints(SymbolTable scope, Diagnostic diagnostic) { NodeUtils.Analyze(scope, TypeParams, diagnostic); }
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); } }
public void OnlyOneInstanceOfTypeIsCreated() { SymbolTable scope = new SymbolTable(); PopulateBuiltinTypes(scope); RType fooTy = GetOrCreateType("Foo"); RType otherFooTy = GetOrCreateType("Foo"); Assert.IsTrue(ReferenceEquals(fooTy, otherFooTy)); }
public SymbolTable(SymbolTable parent) { Parent = parent; }
public SymbolTable([CanBeNull] SymbolTable parent, [NotNull] RppClosureContext closureContext) { Parent = parent; ClosureContext = closureContext; }
public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic) { _classes = NodeUtils.Analyze(scope, _classes, diagnostic); return this; }
public void PreAnalyze(SymbolTable scope) { _classes.ForEach(c => scope.AddType(c.Type)); NodeUtils.PreAnalyze(scope, _classes); }
public SymbolTable([CanBeNull] SymbolTable parent, [NotNull] RppMethodInfo methodInfo) { Parent = parent; AddGenericParametersToScope(methodInfo); }
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; }
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; } }
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; }
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; }