Example #1
0
        private AstItem ReadExternFuncDecl(TokenIterator tokens)
        {
            tokens.PopExpected(TokenKind.Ext);
            tokens.PopExpected(TokenKind.RoundBracketOpen);

            var libFnName = tokens.PopExpected(TokenKind.String);

            tokens.PopExpected(TokenKind.Comma);
            var libName = tokens.PopExpected(TokenKind.String);

            tokens.PopExpected(TokenKind.RoundBracketClose);

            var name = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.RoundBracketOpen);

            var parameters = ReadFuncParameters(tokens);

            var      next       = tokens.Pop();
            DataType returnType = DataType.VOID;

            if (next.Kind == TokenKind.TypeOperator)
            {
                returnType = ReadDataType(tokens);
                tokens.PopExpected(TokenKind.SemiColon);
            }

            return(AstItem.ExternFunctionDecl(name.Value, returnType, parameters, libFnName.Value, libName.Value));
        }
Example #2
0
        private AstItem ReadVector(TokenIterator tokens)
        {
            var name = tokens.Pop();

            var bracket = tokens.Pop();

            if (bracket.Kind != TokenKind.RoundBracketOpen)
            {
                throw new Exception("Unexcepted token after vector name! Expected '(', found: " + bracket);
            }

            var vectorValues   = new List <List <Token> >();
            var valueTokens    = new List <Token>();
            var bracketCounter = 0;
            var token          = tokens.Pop();

            while (token != null)
            {
                if (token.Kind == TokenKind.RoundBracketOpen)
                {
                    bracketCounter += 1;
                    valueTokens.Add(token);
                }
                else if (token.Kind == TokenKind.RoundBracketClose)
                {
                    if (bracketCounter <= 0)
                    {
                        vectorValues.Add(valueTokens);
                        break;
                    }
                    else
                    {
                        bracketCounter -= 1;
                        valueTokens.Add(token);
                    }
                }
                else if (token.Kind == TokenKind.Comma)
                {
                    vectorValues.Add(valueTokens);
                    valueTokens = new List <Token>();
                }
                else
                {
                    valueTokens.Add(token);
                }

                token = tokens.Pop();
            }

            var paramExpressions = new List <AstItem>(vectorValues.Count);

            foreach (var values in vectorValues)
            {
                var expression = ReadExpression(new TokenIterator(values), null);
                paramExpressions.Add(expression);
            }

            //Need to pass the name so SemanticAnalysis knows if "vec" or (i.e.) "vec4f" was used
            return(AstItem.Vector(name.Value, paramExpressions));
        }
Example #3
0
 public void ValidateOperand(AstItem operand)
 {
     if (operand.DataType.Kind != DataTypeKind.POINTER)
     {
         throw new Exception("Can only dereference pointers with '*', given: " + operand.DataType);
     }
 }
Example #4
0
        private AstItem ReadForLoop(TokenIterator tokens)
        {
            //for i in 0..5 [inc 1] {...}
            tokens.PopExpected(TokenKind.For);
            var varName = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.In);
            var startExpression = ReadExpression(tokens, TokenKind.To);

            tokens.PopExpected(TokenKind.To);
            var endExpression = ReadExpression(tokens, new List <TokenKind>()
            {
                TokenKind.CurlyBracketOpen, TokenKind.Inc
            });

            var next = tokens.Pop();

            AstItem incExpression = AstItem.Immediate("1");

            if (next.Kind == TokenKind.Inc)
            {
                incExpression = ReadExpression(tokens, TokenKind.CurlyBracketOpen);
                tokens.PopExpected(TokenKind.CurlyBracketOpen);
            }
            else
            {
                Assert.True(next.Kind == TokenKind.CurlyBracketOpen, "Expected 'inc' or '{', got: " + next);
            }

            var statements = ReadStatements(tokens);

            tokens.PopExpected(TokenKind.CurlyBracketClose);
            return(AstItem.ForLoop(varName.Value, startExpression, endExpression, incExpression, statements));
        }
Example #5
0
 public void ValidateOperand(AstItem operand)
 {
     if (operand.DataType != DataType.BOOL)
     {
         throw new Exception("! operator can only be applied to bool, got: " + operand.DataType);
     }
 }
Example #6
0
        private AstItem ReadNewPointer(TokenIterator tokens)
        {
            tokens.PopExpected(TokenKind.New);

            var token = tokens.Current();

            if (token.Kind == TokenKind.SquareBracketOpen)
            {
                return(AstItem.NewHeapArray(ReadArray(tokens)));
            }
            else
            {
                var subType = ReadDataType(tokens);

                var dataType = DataType.Pointer(subType);

                var amountExpression = AstItem.Immediate("1");
                var current          = tokens.Current();
                if (current != null && current.Kind == TokenKind.RoundBracketOpen)
                {
                    tokens.Pop();
                    amountExpression = ReadExpression(tokens, TokenKind.RoundBracketClose);
                    tokens.PopExpected(TokenKind.RoundBracketClose);
                }

                return(AstItem.NewRawPointer(dataType, amountExpression));
            }
        }
Example #7
0
        private List <AstItem> ReadFuncParameters(TokenIterator tokens)
        {
            var result  = new List <AstItem>();
            var current = tokens.Pop();

            while (current.Kind != TokenKind.RoundBracketClose)
            {
                var name = current;
                if (name.Kind != TokenKind.Word)
                {
                    throw new Exception("Expected parameter name, found " + name);
                }

                tokens.PopExpected(TokenKind.TypeOperator);

                var dataType = ReadDataType(tokens);

                result.Add(AstItem.Parameter(name.Value, dataType));

                current = tokens.Pop();
                if (current.Kind == TokenKind.Comma)
                {
                    current = tokens.Pop();
                }
            }
            return(result);
        }
Example #8
0
        private AstItem ReadDelStatement(TokenIterator tokens)
        {
            tokens.PopExpected(TokenKind.Del);
            var varName = tokens.PopExpected(TokenKind.Word);

            return(AstItem.DelPointer(varName.Value));
        }
Example #9
0
        public void Analyze(CompilerContext context)
        {
            var tokens = new TokenIterator(context.Tokens);
            var result = AstItem.Programm();

            result.Children = Read(tokens);
            context.AST     = result;
        }
Example #10
0
        public DataType GetReturnType(AstItem operand)
        {
            if (operand.DataType.Kind == DataTypeKind.ARRAY || operand.DataType.Kind == DataTypeKind.STRING8)
            {
                return(DataType.Pointer(operand.DataType.ElementType));
            }

            return(DataType.Pointer(operand.DataType));
        }
        public void ValidateOperand(AstItem operand)
        {
            var operandType = operand.DataType;

            if ((operandType.Group == DataTypeGroup.ScalarInteger && !operandType.IsSigned) && operandType.Group != DataTypeGroup.ScalarFloat && operandType.Group != DataTypeGroup.VectorFloat)
            {
                throw new Exception("Unsupported data type for arithmetic negation operator: " + operandType);
            }
        }
Example #12
0
        public void ValidateOperands(AstItem operand1, AstItem operand2)
        {
            //Do not check kind of operand1, just trust it is okay. It can be all kinds of expression items
            Assert.AstItemKind(operand2.Kind, AstItemKind.Type, "Invalid second operand for 'as' operator");

            var typeCast = TypeCast.GetFrom(operand1.DataType.Kind);

            Assert.True(typeCast != null, "Invalid type cast from " + operand1.DataType + " to " + operand2.DataType);
            Assert.True(typeCast.CanCastTo(operand2.DataType.Kind), "Invalid type cast from " + operand1.DataType + " to " + operand2.DataType);
        }
Example #13
0
        private AstItem ReadWhileLoop(TokenIterator tokens)
        {
            //while a > 5 {...}
            tokens.PopExpected(TokenKind.While);
            var whileExpression = ReadExpression(tokens, TokenKind.CurlyBracketOpen);

            tokens.PopExpected(TokenKind.CurlyBracketOpen);
            var statements = ReadStatements(tokens);

            tokens.PopExpected(TokenKind.CurlyBracketClose);
            return(AstItem.WhileLoop(whileExpression, statements));
        }
Example #14
0
        private AstItem ReadIndexAccess(TokenIterator tokenIter)
        {
            var symbol = tokenIter.PopExpected(TokenKind.Word);

            tokenIter.PopExpected(TokenKind.SquareBracketOpen);

            var valueExpression = ReadExpression(tokenIter, TokenKind.SquareBracketClose);

            tokenIter.PopExpected(TokenKind.SquareBracketClose);

            return(AstItem.IndexAccess(symbol.Value, valueExpression));
        }
Example #15
0
        private AstItem ReadVariableAssignment(TokenIterator tokens)
        {
            var name = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.AssigmnentOperator);

            var expression = ReadExpression(tokens, TokenKind.SemiColon);

            tokens.PopExpected(TokenKind.SemiColon);

            return(AstItem.VariableAssignment(name.Value, expression));
        }
Example #16
0
        public void ValidateOperand(AstItem operand)
        {
            var dataType = operand.DataType;

            if (dataType.Kind == DataTypeKind.VOID || dataType.Kind == DataTypeKind.ENUM || dataType.Kind == DataTypeKind.VARS)
            {
                throw new Exception("Cannot create a reference with '&' to: " + dataType);
            }

            if (dataType.MemoryRegion == MemoryRegion.Stack)
            {
                throw new Exception("Cannot create reference with '&' to data on stack: " + operand);
            }
        }
Example #17
0
        public void ValidateOperands(AstItem operand1, AstItem operand2)
        {
            var operand1Type = operand1.DataType;
            var operand2Type = operand2.DataType;

            if (operand1Type.Kind != operand2Type.Kind)
            {
                throw new Exception("Data types of both operands must match for equality operator! " + operand1Type + " != " + operand2Type);
            }

            //Can compare all types!
            //if (!_supportedDataTypes.Contains(operand1Type))
            //    throw new Exception("Datatype not supported for equality operator: " + operand1Type);
        }
Example #18
0
        public void ValidateOperands(AstItem operand1, AstItem operand2)
        {
            var operand1Type = operand1.DataType;
            var operand2Type = operand2.DataType;

            if (operand1Type.Kind != operand2Type.Kind)
            {
                throw new Exception("Data types of both operands must match for boolean operator! " + operand1Type + " != " + operand2Type);
            }

            if (operand1Type.Kind != DataTypeKind.BOOL)
            {
                throw new Exception("Datatype not supported for boolean operator: " + operand1Type);
            }
        }
Example #19
0
        public void ValidateOperands(AstItem operand1, AstItem operand2)
        {
            var operand1Type = operand1.DataType;
            var operand2Type = operand2.DataType;

            if (operand1Type.Kind != operand2Type.Kind)
            {
                throw new Exception("Data types of both operands must match for relational operator '" + Figure + "'! " + operand1Type + " != " + operand2Type);
            }

            //Can only compare scalar values
            if (operand1Type.Group != DataTypeGroup.ScalarInteger && operand1Type.Group != DataTypeGroup.ScalarFloat)
            {
                throw new Exception("Datatype not supported for relational operator '" + Figure + "': " + operand1Type);
            }
        }
Example #20
0
        public void ValidateOperands(AstItem operand1, AstItem operand2)
        {
            if (operand1.Kind != AstItemKind.Type || operand2.Kind != AstItemKind.Identifier)
            {
                throw new Exception("Invalid combination of operands for static access member: " + operand1 + " and " + operand2 + "!");
            }

            var enumType = operand1.DataType;

            Assert.True(enumType != null, "Enum type not found: " + operand1.Identifier);
            Assert.DataTypeKind(enumType.Kind, DataTypeKind.ENUM, "Invalid type for left side of :: operator");

            var element = enumType.EnumElements.Find((e) => e.Name == operand2.Identifier);

            Assert.True(element != null, "Element '" + operand2.Identifier + "' not found in enum '" + operand1.Identifier + "'!");
        }
Example #21
0
        private AstItem ReadEnumDecl(TokenIterator tokens)
        {
            //Skip "enum"
            tokens.Pop();

            var enumName = tokens.PopExpected(TokenKind.Word).Value;

            tokens.PopExpected(TokenKind.CurlyBracketOpen);

            var currentIndex = 0;
            var elements     = new List <AstItem>();
            var current      = tokens.Current();

            while (current.Kind != TokenKind.CurlyBracketClose)
            {
                var elementName = tokens.PopExpected(TokenKind.Word).Value;
                var next        = tokens.Pop();

                switch (next.Kind)
                {
                case TokenKind.AssigmnentOperator:
                    var indexStr = tokens.PopExpected(TokenKind.Number).Value;
                    var index    = int.Parse(indexStr);
                    if (index < currentIndex)
                    {
                        throw new Exception("Invalid enum element index for " + enumName + "." + elementName + "! Must be >= " + currentIndex);
                    }
                    currentIndex = index;
                    next         = tokens.PopExpected(TokenKind.Comma, TokenKind.CurlyBracketClose);
                    break;

                case TokenKind.Comma:
                case TokenKind.CurlyBracketClose:
                    //Nothing to do here, but also no error
                    break;

                default:
                    throw new Exception("Unexpected token in enum declaration: " + next);
                }

                elements.Add(AstItem.EnumElement(elementName, currentIndex));
                currentIndex += 1;
                current       = next;
            }

            return(AstItem.EnumDecl(enumName, elements));
        }
Example #22
0
        private AstItem ReadIndexerAssignment(TokenIterator tokens)
        {
            var name = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.SquareBracketOpen);
            var indexExpression = ReadExpression(tokens, TokenKind.SquareBracketClose);

            tokens.PopExpected(TokenKind.SquareBracketClose);

            tokens.PopExpected(TokenKind.AssigmnentOperator);

            var valueExpression = ReadExpression(tokens, TokenKind.SemiColon);

            tokens.PopExpected(TokenKind.SemiColon);

            return(AstItem.PointerIndexAssignment(name.Value, indexExpression, valueExpression));
        }
Example #23
0
        private AstItem ReadFuncCall(TokenIterator tokens)
        {
            var name = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.RoundBracketOpen);

            var paramValues      = ReadBreaketedList(tokens, TokenKind.RoundBracketOpen, TokenKind.RoundBracketClose, TokenKind.Comma);
            var paramExpressions = new List <AstItem>(paramValues.Count);

            foreach (var valueTokens in paramValues)
            {
                var expression = ReadExpression(new TokenIterator(valueTokens), null);
                paramExpressions.Add(expression);
            }

            return(AstItem.FunctionCall(name.Value, paramExpressions));
        }
Example #24
0
        private AstItem ReadArray(TokenIterator tokens)
        {
            tokens.PopExpected(TokenKind.SquareBracketOpen);
            var firstValue = ReadExpression(tokens, new List <TokenKind> {
                TokenKind.SemiColon, TokenKind.Comma
            });

            var token = tokens.Pop();

            if (token.Kind == TokenKind.SquareBracketClose)
            {
                //Array with only single value
                return(AstItem.ValueArrayDefinition(new List <AstItem>()
                {
                    firstValue
                }));
            }
            if (token.Kind == TokenKind.Comma)
            {
                //Array definition with n values
                var valueTokens = ReadBreaketedList(tokens, TokenKind.SquareBracketOpen, TokenKind.SquareBracketClose, TokenKind.Comma);

                var valueExpressions = new List <AstItem>(valueTokens.Count + 1)
                {
                    firstValue
                };

                foreach (var tokenList in valueTokens)
                {
                    var iterator  = new TokenIterator(tokenList);
                    var valueItem = ReadExpression(iterator, null);
                    valueExpressions.Add(valueItem);
                }

                return(AstItem.ValueArrayDefinition(valueExpressions));
            }
            else if (token.Kind == TokenKind.SemiColon)
            {
                //Array definition with one value and number of items
                var numItemsExpression = ReadExpression(tokens, TokenKind.SquareBracketClose);
                return(AstItem.SizedArrayDefinition(firstValue, numItemsExpression));
            }

            throw new Exception("Unexpected token in array definition: " + token);
        }
Example #25
0
        private void EvaluateConstantExpressions(AstItem item)
        {
            if (item.Kind == AstItemKind.Expression)
            {
                for (int i = 0; i < item.Children.Count; i++)
                {
                    var child = item.Children[i];
                    if (child.Kind == AstItemKind.BinaryOperator && child.BinaryOperator.Figure == "::")
                    {
                        //Convert enum value access like "Enum::Value" to immediate values
                        var typeItem = item.Children[i - 2];
                        Assert.AstItemKind(typeItem.Kind, AstItemKind.Type, "Invalid kind of first operand in expression");
                        var valueItem = item.Children[i - 1];
                        Assert.AstItemKind(valueItem.Kind, AstItemKind.Identifier, "Invalid kind of second operand in expression");

                        var element = typeItem.DataType.EnumElements.Find((e) => e.Name == valueItem.Identifier);
                        Assert.True(element != null, "Enum element with name not found: " + valueItem.Identifier + " in enum: " + typeItem.Identifier);

                        child.Kind     = AstItemKind.Immediate;
                        child.DataType = DataType.U32;
                        child.Value    = element.Index;
                        child.Operator = null;

                        item.Children.RemoveAt(i - 2);
                        item.Children.RemoveAt(i - 2);

                        i -= 2;
                    }
                }
            }
            else
            {
                foreach (var child in item.Children)
                {
                    if (child != null)
                    {
                        EvaluateConstantExpressions(child);
                    }
                }
            }
        }
Example #26
0
        private AstItem ReadFuncDecl(TokenIterator tokens)
        {
            //Skip "fn"
            tokens.Pop();

            var next = tokens.Current();

            if (next.Kind == TokenKind.Ext)
            {
                return(ReadExternFuncDecl(tokens));
            }

            var name = tokens.PopExpected(TokenKind.Word);

            tokens.PopExpected(TokenKind.RoundBracketOpen);

            var parameters = ReadFuncParameters(tokens);

            DataType returnType = DataType.VOID;

            next = tokens.Pop();
            if (next.Kind == TokenKind.TypeOperator)
            {
                returnType = ReadDataType(tokens);
                next       = tokens.Pop();
            }

            if (next.Kind != TokenKind.CurlyBracketOpen)
            {
                throw new Exception("Expected ':' or '{', found " + next);
            }

            var statements = ReadStatements(tokens);

            tokens.PopExpected(TokenKind.CurlyBracketClose);

            return(AstItem.FunctionDecl(name.Value, returnType, parameters, statements));
        }
Example #27
0
        private AstItem ReadIfStatement(TokenIterator tokens)
        {
            tokens.PopExpected(TokenKind.If);
            var expression = ReadExpression(tokens, TokenKind.CurlyBracketOpen);

            tokens.PopExpected(TokenKind.CurlyBracketOpen);
            var statements = ReadStatements(tokens);

            tokens.PopExpected(TokenKind.CurlyBracketClose);

            List <AstItem> elseStatements = null;

            var current = tokens.Current();

            if (current.Kind == TokenKind.Else)
            {
                tokens.PopExpected(TokenKind.Else);
                tokens.PopExpected(TokenKind.CurlyBracketOpen);
                elseStatements = ReadStatements(tokens);
                tokens.PopExpected(TokenKind.CurlyBracketClose);
            }

            return(AstItem.IfStatement(expression, statements, elseStatements));
        }
Example #28
0
 public void Optimize(AstItem programItem)
 {
     Assert.AstItemKind(programItem.Kind, AstItemKind.Programm, "Invalid AST item for optimization");
     EvaluateConstantExpressions(programItem);
 }
Example #29
0
 public void ValidateOperands(AstItem operand1, AstItem operand2)
 {
 }
Example #30
0
 public DataType GetReturnType(AstItem operand1, AstItem operand2)
 {
     return(DataType.VOID);
 }