Example #1
0
 private static void ValidateEntryPoint(CodeGenerator generator, RppOptions options, Diagnostic diagnostic)
 {
     if (options.Library == false && !generator.HasMain())
     {
         diagnostic.Error(101, "Program doesn't contain a valid entry point");
     }
 }
Example #2
0
 public static Type CodeGenAndGetType(RppProgram program, string typeName, Diagnostic diagnostic)
 {
     var assembly = CodeGen(program, diagnostic);
     Type arrayTy = assembly.GetType(typeName);
     Assert.IsNotNull(arrayTy);
     return arrayTy;
 }
Example #3
0
        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;
        }
Example #4
0
        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;
        }
Example #5
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;
            }
        }
Example #6
0
        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;
        }
Example #7
0
        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;
        }
Example #8
0
        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);
        }
Example #9
0
        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;
        }
Example #10
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;
        }
Example #11
0
        private static int RunAndReturnExitCode(RppOptions options)
        {
            Diagnostic diagnostic = new Diagnostic();
            RppCompiler.CompileAndSave(options, diagnostic);

            diagnostic.Report();

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

            return 0;
        }
Example #12
0
        public void NonInitializedLocalVar()
        {
            const string code = @"
object Main
{
    def main: Unit = {
        val k: Int
    }
}
";
            Diagnostic diagnostic = new Diagnostic();
            Utils.ParseAndAnalyze(code, diagnostic);
            Assert.AreEqual(1, diagnostic.Errors.Count());
            Assert.AreEqual(102, diagnostic.Errors.First().Code);
        }
Example #13
0
        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;
        }
Example #14
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;
        }
Example #15
0
        public static void CompileAndSave(RppOptions options, Diagnostic diagnostic)
        {
            string outFileName = GetOutputFileName(options);

            Assembly stdlib = null;
            if (!options.Nostdlib)
            {
                stdlib = FindStdlib();
            }

            CodeGenerator generator = Compile(program => Parse(options.InputFiles, program), diagnostic, stdlib, outFileName);
            if (generator != null)
            {
                ValidateEntryPoint(generator, options, diagnostic);
                if (!diagnostic.Errors.Any())
                {
                    generator.Save(options.Library ? ApplicationType.Library : ApplicationType.Application);
                }
            }
        }
Example #16
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 #17
0
        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);
        }
Example #18
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;
        }
Example #19
0
 public static RppProgram ParseAndAnalyze(string code, Diagnostic diagnostic)
 {
     RppProgram program = Parse(code);
     CodeGen(program, diagnostic);
     return program;
 }
Example #20
0
        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;
        }
Example #21
0
 public static Type ParseAndCreateType(string code, string typeName, Diagnostic diagnostic)
 {
     RppProgram program = Parse(code);
     Assert.IsNotNull(program);
     return CodeGenAndGetType(program, typeName, diagnostic);
 }
Example #22
0
 public static IEnumerable<Type> ParseAndCreateTypes(string code, IEnumerable<string> typesNames, Diagnostic diagnostic)
 {
     RppProgram program = Parse(code);
     var assembly = CodeGen(program, diagnostic);
     return typesNames.Select(assembly.GetType);
 }
Example #23
0
 public ResolveParamTypes(Diagnostic diagnostic)
 {
     _diagnostic = diagnostic;
 }
Example #24
0
 public CreateRType(Diagnostic diagnostic)
 {
     _diagnostic = diagnostic;
 }
Example #25
0
 public void ResolveGenericTypeConstraints(SymbolTable scope, Diagnostic diagnostic)
 {
     NodeUtils.Analyze(scope, TypeParams, diagnostic);
 }
Example #26
0
        public static void Main()
        {
            const string code = @"
abstract class XIterator[+A] {
  def hasNext: Boolean

  def next(): A

  def copy(): XIterator[A]

  protected def foreach(f: A => Unit): Unit =
    while (hasNext())
      f(next())

  def toList: XList[A] = {
    var res = XList[A]()
    foreach((item) => {
      res = new XCons(item, res)
    })
    res.reverse()
  }

  def count: Int = {
    var c = 0
    foreach(item => c = c + 1)
    c
  }

  def toArray[B <: A]: Array[B] = {
    val res = new Array[B](count())
    var index = 0
    foreach((item) => {
      res(index) = next()
      index = index + 1
    })
    res
  }
}

abstract class XIterable[+A] {
  def iterator: XIterator[A]
}

class XListIterator[A](var list: XList[A]) extends XIterator[A] {
  override def hasNext: Boolean = !list.isEmpty

  override def next(): A = {
    if (list.isEmpty)
      throw new Exception

    val item = list.head
    list = list.tail
    item
  }

  override def copy(): XIterator[A] = new XListIterator(list)
}

class XArrayIterator[A](var array: Array[A]) extends XIterator[A] {
  private var index: Int = 0

  override def hasNext: Boolean = array.length > index

  override def next(): A = {
    val item = array(index)
    index += 1
    item
  }

  override def copy(): XIterator[A] = new XArrayIterator(array)
}

class XMapIterator[A, U](val iter: XIterator[A], val f: A => U) extends XIterator[U] {
  override def hasNext(): Boolean = iter.hasNext()

  override def next(): U = f(iter.next())

  override def count(): Int = iter.count()

  override def copy(): XIterator[U] = new XMapIterator(iter.copy(), f)
}

class XFilterIterator[A](val iter: XIterator[A], val f: A => Boolean) extends XIterator[A] {
  private var item: Option[A] = None

  calcNext()

  private def calcNext(): Unit = {
    while (iter.hasNext && item.isEmpty) {
      val it = iter.next()
      if (f(it)) {
        item = Some[A](it)
      }
    }
  }

  override def hasNext: Boolean = item.isDefined

  override def next(): A = {
    val nextItem = item.get
    calcNext()
    nextItem
  }


  override def copy(): XIterator[A] = new XFilterIterator(iter.copy(), f)
}

abstract class XList[+A] extends XIterable[A] {
  def head: A
  def tail: XList[A]
  def isEmpty: Boolean
  def asStream: XIterator[A] = iterator()
  override def iterator: XIterator[A] = new XListIterator[A](this)

  def reverse: XList[A] = {
    val iter = iterator()
    val k: A = iter.next()
    var res = XList[A]()

    while (iter.hasNext()) {
      res = new XCons[A](iter.next(), res)
    }
    res
  }

    def map[U](f: A => U): XList[U] = XFunc.map[A, U](iterator, f).toList
}

object XFunc {
  def map[A, U](iter: XIterator[A], f: A => U): XIterator[U] = new XMapIterator(iter, f)
}

object XNil extends XList[Nothing] {
  override def isEmpty: Boolean = true
  override def head: Nothing = throw new Exception
  override def tail: XList[Nothing] = throw new Exception
}

class XCons[A](val _head: A, val _tail: XList[A]) extends XList[A] {
  override def isEmpty: Boolean = false
  override def head: A = _head
  override def tail: XList[A] = _tail
}

object XList {
  def apply[A](args: A*): XList[A] = {
    if (args.length() == 0) {
      XNil
    } else {
      var k = args.length() - 1
      var list: XList[A] = XNil
      while (k >= 0) {
        val it: A = args(k)
        list = new XCons[A](it, list)
        k = k - 1
      }
      list
    }
  }
}

object Main {
    def main: Array[Int] = {
        val nums = XList[Int](1, 2, 3, 4, 5)
        val dbls = nums.map(x => x * 2)
        dbls.iterator.toArray
    }
}
";

            Diagnostic diagnostic = new Diagnostic();
            CodeGenerator codeGen = RppCompiler.Compile(program => RppCompiler.Parse(code, program), diagnostic, GetStdlibAssembly(), "Sample.dll");
            if (diagnostic.HasError())
            {
                diagnostic.Report();
            }
            else
            {
                Debug.Assert(codeGen != null, "codeGen != null");
                codeGen.Save(ApplicationType.Library);
            }
        }
Example #27
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;
            }
        }
Example #28
0
 public SemanticAnalyzerStage1(Diagnostic diagnostic)
 {
     _diagnostic = diagnostic;
 }
Example #29
0
 public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
 {
     _classes = NodeUtils.Analyze(scope, _classes, diagnostic);
     return this;
 }
Example #30
0
 public override IRppNode Analyze(SymbolTable scope, Diagnostic diagnostic)
 {
     Expr = Expr.Analyze(scope, diagnostic) as IRppExpr;
     return this;
 }