示例#1
0
        public void TestExpressionFunctionReturnTypeBinding()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) -> return new MyClass2()" +
                               "    }" +
                               "" +
                               "    class MyClass2" +
                               "    {" +
                               "        " +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();
            var semanticModel = binder.Bind(new List<CompilationUnitSyntax> { ast }).Single();

            var boundNamespace = semanticModel.Namespaces.Single(x => x.Name == "MyNamespace");
            var expectedFunctionReturnType = boundNamespace.Types.Single(x => x.Name == "MyClass2");
            var function = boundNamespace.Types.Single(x => x.Name == "MyClass").Functions.Single(x => x.Name == "Add");
            Assert.AreSame(expectedFunctionReturnType, function.ReturnType);
        }
示例#2
0
        public Expressions Parse(string sourceText) //API entry point
        {
            ResetParserState();
            sourceText += '\0';  //TOOD: figure out how newline is interpreted in a c# string
            m_Lexer.Lex(sourceText, Lexer.Lexer.IncludeWhiteSpaceTokens.No, Lexer.Lexer.IncludeEofToken.Yes);
            m_tokenList = m_Lexer.GetTokens();

            if (m_Lexer.m_Diagnostics.Count > 0)
            {
                foreach (var errorMessage in m_Lexer.m_Diagnostics)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Lexer: " + errorMessage);
                    Console.ResetColor();
                }

                return(null);
            }

            switch (Peek().TokenType)
            {
            //ParseStatement,....
            default:
                return(ParseExpression());
            }
        }
示例#3
0
        public void TestClass()
        {
            var lexer = new Lexer.Lexer();
            var tokens =
                lexer.Lex(
                    string.Format(NamespaceSource, string.Format(ClassSource, string.Empty, string.Empty, string.Empty)));
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            Assert.IsInstanceOf<CompilationUnitSyntax>(ast);
            Assert.IsNotEmpty(ast.Namespaces);
            Assert.IsNotEmpty(ast.Namespaces[0].Classes);
            Assert.AreEqual("ClassSample", ast.Namespaces[0].Classes[0].Name.Value);
            Assert.AreEqual("DSampleProtocol", ast.Namespaces[0].Classes[0].ProtocolName.Value);
        }
示例#4
0
        public void TestExpressionFunction()
        {
            const string functionSource = "func FunctionSample(int a, int b, int c) -> return a * b * c";

            var lexer = new Lexer.Lexer();
            var tokens =
                lexer.Lex(
                    string.Format(
                        NamespaceSource,
                        string.Format(ClassSource, functionSource, string.Empty, string.Empty)));
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            Assert.IsNotEmpty(ast.Namespaces[0].Classes[0].Functions);
            Assert.IsInstanceOf<FunctionSyntax>(ast.Namespaces[0].Classes[0].Functions[0]);
            Assert.AreEqual("FunctionSample", ast.Namespaces[0].Classes[0].Functions[0].Name.Value);
        }
示例#5
0
        public Parser(string text)
        {
            var tokens = new List <SyntaxToken>();

            var         lexer = new Lexer.Lexer(text);
            SyntaxToken token;

            do
            {
                token = lexer.Lex();

                if (token.Kind != TokenType.Whitespace &&
                    token.Kind != TokenType.Bad)
                {
                    tokens.Add(token);
                }
            } while (token.Kind != TokenType.EndOfFile);

            _tokens = tokens.ToArray();
            _diagnostics.AddRange(lexer.Diagnostics);
        }
示例#6
0
        public void TestFieldTypeToVariableBinding()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        var field : false" +
                               "        var field2 : new MyClass2()" +
                               "        func MyFunc()" +
                               "        {" +
                               "            var i : field" +
                               "            var i2 : field2" +
                               "        }" +
                               "    }" +
                               "" +
                               "    class MyClass2" +
                               "    {" +
                               "        " +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();
            var semanticModel = binder.Bind(new List<CompilationUnitSyntax> { ast }).Single();

            var boundNamespace = semanticModel.Namespaces.Single(x => x.Name == "MyNamespace");
            var referencedBoundType = boundNamespace.Types.Single(x => x.Name == "MyClass2");
            var boundType = boundNamespace.Types.Single(x => x.Name == "MyClass");
            var boundFunction = (BoundFunction)boundType.Functions.Single(x => x.Name == "MyFunc");
            Assert.IsInstanceOf<BoolCompilerGeneratedType>(
                ((IBoundMember)((BoundScopeStatement)boundFunction.Statements).Statements[0]).Type);
            Assert.AreSame(
                ((IBoundMember)((BoundScopeStatement)boundFunction.Statements).Statements[1]).Type,
                referencedBoundType);
        }
示例#7
0
        public void Test_InfixCall_Types()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass2" +
                               "    {" +
                               "        infix func Add(int a, int b) -> return a + b" +
                               "        func Foo()" +
                               "        {" +
                               "            var a : 1 Add 2" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            var binder = new Binder();
            var boundCompilationUnits = binder.Bind(new List<CompilationUnitSyntax>() { ast });

            var myClass2Type = boundCompilationUnits[0].Namespaces[0].Types.Single();
            var fooFunction = myClass2Type.Functions.Single(x => x.Name == "Foo");
            var addFunction = myClass2Type.Functions.Single(x => x.Name == "Add");

            Assert.IsInstanceOf<BoundFunction>(addFunction);
            Assert.IsTrue(((BoundFunction)addFunction).IsInfixFunction);
            Assert.IsInstanceOf<BoundFunction>(fooFunction);
            var boundFunction = (BoundFunction)fooFunction;
            Assert.IsInstanceOf<BoundScopeStatement>(boundFunction.Statements);
            var boundScopeStatement = (BoundScopeStatement)boundFunction.Statements;
            Assert.IsInstanceOf<BoundVariableDeclarationStatement>(boundScopeStatement.Statements[0]);
            var boundVariableDeclarationStatement = (BoundVariableDeclarationStatement)boundScopeStatement.Statements[0];
            Assert.IsInstanceOf<BoundInvocationExpression>(boundVariableDeclarationStatement.BoundExpression);
            var boundInvocationExpression = (BoundInvocationExpression)boundVariableDeclarationStatement.BoundExpression;
            Assert.IsInstanceOf<BoundMemberExpression>(boundInvocationExpression.ToInvoke);
            var boundMemberExpression = (BoundMemberExpression)boundInvocationExpression.ToInvoke;
            Assert.AreSame(addFunction, boundMemberExpression.BoundMember);
        }
示例#8
0
        public void Test_GenericConstraints(string constraint)
        {
            const string template = "class SomeGenericClass!(T) where T {0}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(string.Format(template, opSrc));
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc(constraint), Throws.Nothing);
        }
示例#9
0
        public void Test_ArrayAccessInvalidParameter_Throws()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b)" +
                               "        {   " +
                               "            var c : new int[1][1]" +
                               "            var d : c[1]" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>()
                      .With.Message.EqualTo("Parameter count (1) must match array dimension count (2)"));
        }
示例#10
0
        public void Test_SwitchStatement_CasesTypeMustMatchSwitchConditionType()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) " +
                               "        { " +
                               "            switch(a)" +
                               "            {" +
                               "                case \"LOL\" -> Add(1, 0)" +
                               "            }" +
                               "        }" +
                               "    }" +
                               "" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>()
                      .With.Message.EqualTo("Switch cases condition type must match switch condition type"));
        }
示例#11
0
        public void Test_RecursivExpressionFunction_DoesThrow()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) -> return Add(1, 2)" +
                               "    }" +
                               "" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>().With.Message.EqualTo("Add Type cannot be inferred"));
        }
示例#12
0
        public void Test_Operator_FunctionMapping()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass2" +
                               "    {" +
                               "        operator Add(MyClass2 opA, MyClass2 opB) -> return new MyClass2()" +
                               "        operator Sub(MyClass2 opA, MyClass2 opB) -> return new MyClass2()" +
                               "        operator Mult(MyClass2 opA, MyClass2 opB) -> return new MyClass2()" +
                               "        operator Div(MyClass2 opA, MyClass2 opB) -> return new MyClass2()" +
                               "        operator Pow(MyClass2 opA, MyClass2 opB) -> return new MyClass2()" +
                               "        operator Range(MyClass2 opA, MyClass2 opB) -> return new MyClass2[1]" +
                               "        operator In(MyClass2 opA, MyClass2 opB) -> return true" +
                               "    }" +
                               "    " +
                               "    class TestClass" +
                               "    {" +
                               "        func TestBinaryFunc()" +
                               "        {" +
                               "            var instance : new MyClass2()" +
                               "            var testAdd : instance + new MyClass2()" +
                               "            var testSub : instance - new MyClass2()" +
                               "            var testMult : instance * new MyClass2()" +
                               "            var testDiv : instance / new MyClass2()" +
                               "            var testPow : instance ^ new MyClass2()" +
                               "            var testRange : instance..newMyClass2()" +
                               "            var testIn : instance in new myClass2[10]" +
                               "        }" +
                               "" +
                               "" +
                               "        func TestAssignFunc()" +
                               "        {" +
                               "            var instance : None MyClass2" +
                               "            instance +: new MyClass2()" +
                               "            instance -: new MyClass2()" +
                               "            instance *: new MyClass2()" +
                               "            instance ^: new MyClass2()" +
                               "            instance /: new MyClass2()" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            var binder = new Binder();
            var boundCompilationUnit = binder.Bind(new List<CompilationUnitSyntax>() { ast }).Single();

            var boundNamespace = boundCompilationUnit.Namespaces.Single(x=>x.Name== "MyNamespace");
            var operatorClass = boundNamespace.Types.Single(x=>x.Name== "MyClass2");
            var testClass = boundNamespace.Types.Single(x=>x.Name == "TestClass");
            var testBinaryFunc = testClass.Functions.Single(x=>x.Name== "TestBinaryFunc");
            var testAssignFunc = testClass.Functions.Single(x=>x.Name== "TestAssignFunc");
        }
示例#13
0
        public void Test_MemberAccessExpressionBinding()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) -> return a * b" +
                               "    }" +
                               "" +
                               "    class MyClass2" +
                               "    {" +
                               "        var addMethod : new MyClass().Add" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            var boundCompilationUnit = binder.Bind(new List<CompilationUnitSyntax>() { ast }).Single();
            var function =
                boundCompilationUnit.Namespaces[0].Types.Single(x => x.Name == "MyClass")
                                                  .Functions.Single(x => x.Name == "Add");
            var field =
                boundCompilationUnit.Namespaces[0].Types.Single(x => x.Name == "MyClass2")
                                                  .Fields.Single(x => x.Name == "addMethod");
            Assert.That(
                () => field.Type,
                Is.InstanceOf<FunctionCompilerGeneratedType>()
                  .And.Property("ReturnType")
                  .InstanceOf<IntCompilerGeneratedType>());
            CollectionAssert.AllItemsAreInstancesOfType(
                ((FunctionCompilerGeneratedType)field.Type).ParameterTypes,
                typeof(IntCompilerGeneratedType));
        }
示例#14
0
        public void Test_TryCatch()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class GenericClass(TypeA, TypeB)" +
                               "    {" +
                               "        Constructor(TypeA arg1, TypeB arg2)" +
                               "        {" +
                               "            Try" +
                               "            {" +
                               "            }" +
                               "            catch(Error)" +
                               "            {" +
                               "            }" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            Assert.DoesNotThrow(() => parser.Parse());
        }
示例#15
0
        public void Test_primary_Constructor()
        {
            const string code = @"namespace MyNamespace" +
                                    "{" +
                                    "    class MyClass" +
                                    "    {" +
                                    "       primary Constructor(int val)" +
                                    "       {" +
                                    "       }" +
                                    "    }" +
                                    "}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(opSrc);
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc(code), Throws.Nothing);
        }
示例#16
0
        public void Test_Optional()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class Class" +
                               "    {" +
                               "        Constructor(Optional!(int) i, Optional!(string) s)" +
                               "        {" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            Assert.DoesNotThrow(() => parser.Parse());
        }
示例#17
0
        public void Test_InvalidOperatorNames_Throw()
        {
            const string template = "namespace MyNamespace" +
                                    "{{" +
                                    "    class MyClass2" +
                                    "    {{" +
                                    "        {0}" +
                                    "    }}" +
                                    "}}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(string.Format(template, opSrc));
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc("operator Addd(MyClassName opA, MyClassName opB) -> return true"), Throws.InstanceOf<KiwiSyntaxException>().With.Message.EqualTo("Invalid operator function name 'Addd'"));
        }
示例#18
0
        public void Test_Infix_NamespaceLevel()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    infix func Add(int a, int b) -> return a + b" +
                               "    class MyClass2" +
                               "    {" +
                               "        func Foo()" +
                               "        {" +
                               "            var a : 1 Add 2" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            var namespaceSyntax = ast.Namespaces.Single(x => x.Name.Value == "MyNamespace");
            var infixFunction = namespaceSyntax.Functions.Single(x=>x.Name.Value == "Add");
            Assert.IsInstanceOf<InfixFunctionSyntax>(infixFunction);
        }
示例#19
0
        public void Test_GenericLocalFunction_Call()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    func GenericFunction!(TypeA, TypeB)(TypeA a, TypeB b)" +
                               "    {" +
                               "        let anonFunc : func!(TypeX, TypeY)(TypeX x, TypeY y) -> return x" +
                               "        anonFunc!(a, a)" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            Assert.DoesNotThrow(() => parser.Parse());
        }
示例#20
0
        public void Test_GenericFunction_NamespaceLevel()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    func GenericFunction!(TypeA, TypeB)(TypeA a, TypeB b)" +
                               "    {" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            Assert.DoesNotThrow(() => parser.Parse());
        }
示例#21
0
        public void Test_IsExpression()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) -> return a * b" +
                               "    }" +
                               "" +
                               "    class MyClass2" +
                               "    {" +
                               "        var myClassField : new MyClass()" +
                               "        func Foo() -> bool" +
                               "        {" +
                               "            return myClassField is MyClass" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            var boundCompilationUnit = binder.Bind(new List<CompilationUnitSyntax>() { ast }).Single();
            var type = boundCompilationUnit.Namespaces[0].Types.Single(x => x.Name == "MyClass");
            var function =
                (BoundFunction)
                boundCompilationUnit.Namespaces[0].Types.Single(x => x.Name == "MyClass2")
                                                  .Functions.Single(x => x.Name == "Foo");
            var returnStatement = (BoundReturnStatement)((BoundScopeStatement)function.Statements).Statements[0];
            var boundBinaryExpression = (BoundBinaryExpression)returnStatement.Expression;
            Assert.AreEqual(BinaryOperators.Is, boundBinaryExpression.Operator);
            Assert.IsInstanceOf<BoundTypeExpression>(boundBinaryExpression.Right);
            Assert.AreSame(((BoundTypeExpression)boundBinaryExpression.Right).ReferencedType, type);
        }
示例#22
0
        public void Test_IsExpression_ThrowsTypeNotDefined()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) -> return a * b" +
                               "    }" +
                               "" +
                               "    class MyClass2" +
                               "    {" +
                               "        var myClassField : new MyClass()" +
                               "        func Foo() -> bool" +
                               "        {" +
                               "            return myClassField is MyClassS" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>().With.Message.EqualTo("MyClassS undefined Type"));
        }
示例#23
0
        public void Test_ValidOperatorNames_DontThrow(string opCode)
        {
            const string template = "namespace MyNamespace" +
                                    "{{" +
                                    "    class MyClass2" +
                                    "    {{" +
                                    "        {0}" +
                                    "    }}" +
                                    "}}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(string.Format(template, opSrc));
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc(opCode), Throws.Nothing);
        }
示例#24
0
        public void Test_ObjectCreationExpression_ThrowsNoConstructorWithoutArguments()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        Constructor(int a){}" +
                               "    }" +
                               "    class MyClass2" +
                               "    {" +
                               "        func Foo()" +
                               "        {" +
                               "            var a : new MyClass()" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>()
                      .With.Message.EqualTo("MyNamespace.MyClass has no constructor without arguments."));
        }
示例#25
0
        public void TestExpressions(string statementSource, Type type)
        {
            var lexer = new Lexer.Lexer();
            var tokens =
                lexer.Lex(
                    string.Format(
                        NamespaceSource,
                        string.Format(
                            ClassSource,
                            string.Format(FunctionSource, statementSource),
                            string.Empty,
                            string.Empty)));
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();
            Assert.IsInstanceOf(
                type,
                ((ReturnStatementSyntax)((ScopeStatementSyntax)ast.Namespaces[0].Classes[0].Functions[0].Statements).Statements[0]).Expression);
        }
示例#26
0
        public void Test_Function_VisibilityModifiers(string code)
        {
            const string template = "namespace MyNamespace" +
                                    "{{" +
                                    "    class MyClass" +
                                    "    {{" +
                                    "        {0}" +
                                    "    }}" +
                                    "}}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(string.Format(template, opSrc));
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc(code), Throws.Nothing);
        }
示例#27
0
        public void Test_IfElseExpression_IfTrueIfFalseTypeMustBeEqual()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, float b) -> return if(true) a else b" +
                               "    }" +
                               "" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>()
                      .With.Message.EqualTo("IfTrue and IfFalse expression Type must match"));
        }
示例#28
0
        public void Test_Scope_VariableNotDefined()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) " +
                               "        { " +
                               "            {" +
                               "                var i : 1337 + b" +
                               "            }" +
                               "            var c : a * b * i" +
                               "        }" +
                               "    }" +
                               "" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>().With.Message.EqualTo("i not defined"));
        }
示例#29
0
        public void Test_Field_without_initializer_isValid()
        {
            const string code = @"namespace MyNamespace" +
                                    "{" +
                                    "    class MyClass" +
                                    "    {" +
                                    "       private var _some" +
                                    "       primary Constructor(int val)" +
                                    "       {" +
                                    "           _some = val" +
                                    "       }" +
                                    "    }" +
                                    "}";

            var parserFunc = new Action<string>(
                opSrc =>
                {
                    var lexer = new Lexer.Lexer();
                    var tokens = lexer.Lex(opSrc);
                    var parser = new Parser.Parser(tokens);
                    parser.Parse();
                });

            Assert.That(() => parserFunc(code), Throws.Nothing);
        }
示例#30
0
        public void Test_VariableWithSameName_Throws()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b)" +
                               "        {" +
                               "            var a : 1" +
                               "            var b : 2" +
                               "            var a : 1" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();
            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax> { ast }),
                Throws.TypeOf<KiwiSemanticException>().With.Message.EqualTo("a already defined."));
        }
示例#31
0
        public void Test_IfStatement_IfConditionMustBeBool()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class MyClass" +
                               "    {" +
                               "        func Add(int a, int b) " +
                               "        { " +
                               "            if(a)" +
                               "            {" +
                               "                " +
                               "            }" +
                               "        }" +
                               "    }" +
                               "" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            var ast = parser.Parse();

            var binder = new Binder();

            Assert.That(
                () => binder.Bind(new List<CompilationUnitSyntax>() { ast }),
                Throws.InstanceOf<KiwiSemanticException>().With.Message.EqualTo("If condition must be of Type Bool"));
        }
示例#32
0
        static void Main(string[] args)
        {
            bool   interpret = false, assemble = false;
            string input = "", outpath = "", filename = "";

            if (args.Length == 0)
            {
                Console.Error.WriteLine(helpMsg);
                Environment.Exit(1);
            }

            for (int i = 0; i < args.Length; i++)
            {
                string arg = args[i];
                switch (arg)
                {
                case "-i":
                case "-interpret":
                {
                    interpret = true;
                    break;
                }

                case "-o":
                {
                    outpath = args[++i];

                    // -o and -i can not be used together
                    if (interpret)
                    {
                        Console.Error.WriteLine("-i and -o cannot be used together");
                        Console.Error.WriteLine(helpMsg);
                        Environment.Exit(1);
                    }
                    break;
                }

                case "-a":
                {
                    assemble = true;

                    // -r and -i can not be used together
                    if (interpret)
                    {
                        Console.Error.WriteLine("-i and -a cannot be used together");
                        Console.Error.WriteLine(helpMsg);
                        Environment.Exit(1);
                    }
                    break;
                }

                default:
                {
                    try
                    {
                        input = File.ReadAllText(arg);

                        // This regular expression extracts the filename and discards the rest of the path and the file extension
                        filename = Regex.Match(arg, @"^.*[\\|\/](.+?)\.[^\.]+$").Groups[1].ToString();
                    }
                    catch (Exception e) when(e is FileNotFoundException || e is DirectoryNotFoundException)
                    {
                        Console.Error.WriteLine("File Not Found: " + arg);
                        Environment.Exit(1);
                    }
                    break;
                }
                }
            }

            // if no output path given, output the file to the working dir
            if (outpath == "")
            {
                outpath = ".";
            }

            Stopwatch sw = new Stopwatch();

            Console.WriteLine("Lexing...");

            sw.Start();
            var lexout = lexer.Lex(input);

            sw.Stop();

            Console.WriteLine($"New Lex Time: {sw.ElapsedMilliseconds}ms");

            sw.Reset();

            Console.WriteLine("Parsing...");
            var parseOut = parser.Parse(lexout);


            if (interpret)
            {
                Console.WriteLine("Interpreting...\n");

                sw.Start();
                interpreter.Interpret(parseOut);
                sw.Stop();

                Console.WriteLine($"Interpret Time: {sw.ElapsedMilliseconds}ms");
            }
            else
            {
                Console.WriteLine("Compiling...");

                sw.Start();
                var jasmin = codegen.Compile(parseOut, filename);
                sw.Stop();

                Console.WriteLine($"Compile Time: {sw.ElapsedMilliseconds}ms");

                string outFile = outpath + "/" + filename + ".j";
                File.WriteAllText(outFile, jasmin);
                Console.WriteLine($"{outFile} created");

                if (assemble)
                {
                    Process p = new Process();
                    p.StartInfo.FileName  = "java";
                    p.StartInfo.Arguments = $"-jar jasmin.jar {outFile}";

                    Console.WriteLine("Assembling...");
                    p.Start();

                    p.WaitForExit();
                }
            }
            Console.WriteLine("Done!");
        }
示例#33
0
        public void Test_GenericClass()
        {
            const string src = "namespace MyNamespace" +
                               "{" +
                               "    class GenericClass(TypeA, TypeB)" +
                               "    {" +
                               "        var mutable1 : None TypeA;" +
                               "        var mutable2 : None TypeB;" +
                               "        Constructor(TypeA arg1, TypeB arg2)" +
                               "        {" +
                               "            mutable1 : arg1;" +
                               "            mutable2 : arg2;" +
                               "        }" +
                               "    }" +
                               "}";

            var lexer = new Lexer.Lexer();
            var tokens = lexer.Lex(src);
            var parser = new Parser.Parser(tokens);

            Assert.DoesNotThrow(() => parser.Parse());
        }