Пример #1
0
        private object Visit(UnaryOperationNode node)
        {
            var value = Visit(node.Expression);

            if (node.Operation.Type == Tokens.Subtract)
            {
                if (value is int)
                {
                    return(-((int)value));
                }
                if (value is float)
                {
                    return(-((float)value));
                }
                ReportError(new Exception("You can only apply unary operations (+,-) to numeric types!"));
            }
            else if (node.Operation.Type == Tokens.Not)
            {
                if (value is bool)
                {
                    return(!((bool)value));
                }
                ReportError(new Exception("You can only apply unary operations (!) to boolean types!"));
            }
            return(null);
        }
        public SymConst Visit(UnaryOperationNode node)
        {
            // todo: maybe implement other unary operations
            var exprConst = node.Expr.Accept(this);

            switch (node.Operation)
            {
            case OperatorToken operatorToken:

                switch (operatorToken.Value)
                {
                case Constants.Operators.Minus:

                    switch (exprConst)
                    {
                    case SymIntConst intConst:
                        return(new SymIntConst(intConst.Name, intConst.Type, -intConst.Value, SymVarOrConst.SymLocTypeEnum.Global));

                    case SymDoubleConst doubleConst:
                        return(new SymDoubleConst(doubleConst.Name, doubleConst.Type, -doubleConst.Value, SymVarOrConst.SymLocTypeEnum.Global));
                    }
                    break;
                }
                break;
            }
            throw EvalException();
        }
Пример #3
0
        public override DynValue Visit(UnaryOperationNode unaryOperationNode)
        {
            var operand = Visit(unaryOperationNode.Operand);

            switch (unaryOperationNode.Type)
            {
            case UnaryOperationType.Plus:
                return(new DynValue(+operand.Number));

            case UnaryOperationType.Minus:
                return(new DynValue(-operand.Number));

            case UnaryOperationType.Length:
            {
                switch (operand.Type)
                {
                case DynValueType.String:
                    return(new DynValue(operand.String.Length));

                case DynValueType.Table:
                    return(new DynValue(operand.Table.Count));

                default: throw new RuntimeException($"Length operator doesn't support the type '{operand.Type}'", unaryOperationNode.Line);
                }
            }

            case UnaryOperationType.ToString:
                return(operand.AsString());

            case UnaryOperationType.NameOf:
            {
                if (unaryOperationNode.Operand is VariableNode variable)
                {
                    return(new DynValue(variable.Name));
                }

                throw new RuntimeException("Attempt to get a name of a non-variable symbol.", unaryOperationNode.Line);
            }

            case UnaryOperationType.Negation:
            {
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt of logical negation of non-numerical type '{operand.Type}'", unaryOperationNode.Line);
                }

                if (operand.Number != 0)
                {
                    return(new DynValue(0));
                }
                else
                {
                    return(new DynValue(1));
                }
            }

            default: throw new RuntimeException("Unknown unary operation type.", unaryOperationNode.Line);
            }
        }
Пример #4
0
        public void Accept(UnaryOperationNode node)
        {
            switch (node.UnaryOperation)
            {
            case UnaryOperation.BitwiseNot:
                node.Target.Visit(this);
                emit(node.SourceLocation, InstructionType.UnaryOperation, (int)UnaryOperation.BitwiseNot);
                break;

            case UnaryOperation.LogicalNot:
                node.Target.Visit(this);
                emit(node.SourceLocation, InstructionType.UnaryOperation, (int)UnaryOperation.LogicalNot);
                break;

            case UnaryOperation.Negate:
                node.Target.Visit(this);
                emit(node.SourceLocation, InstructionType.UnaryOperation, (int)UnaryOperation.Negate);
                break;

            case UnaryOperation.PostDecrement:
            case UnaryOperation.PostIncrement:
            case UnaryOperation.PreDecrement:
            case UnaryOperation.PreIncrement:
                if (node.Target is IdentifierNode)
                {
                    string             identifier = ((IdentifierNode)node.Target).Identifier;
                    HassiumInstruction loadInstruction, storeInstruction;
                    if (table.ContainsGlobalSymbol(identifier))
                    {
                        loadInstruction  = new HassiumInstruction(node.SourceLocation, InstructionType.LoadGlobalVariable, table.GetGlobalSymbol(identifier));
                        storeInstruction = new HassiumInstruction(node.SourceLocation, InstructionType.StoreGlobalVariable, table.GetGlobalSymbol(identifier));
                    }
                    else
                    {
                        loadInstruction  = new HassiumInstruction(node.SourceLocation, InstructionType.LoadLocal, table.GetSymbol(identifier));
                        storeInstruction = new HassiumInstruction(node.SourceLocation, InstructionType.StoreLocal, table.GetSymbol(identifier));
                    }
                    methodStack.Peek().Instructions.Add(loadInstruction);
                    if (node.UnaryOperation == UnaryOperation.PostDecrement || node.UnaryOperation == UnaryOperation.PostIncrement)
                    {
                        emit(node.SourceLocation, InstructionType.Duplicate);
                    }
                    emit(node.SourceLocation, InstructionType.Push, 1);
                    emit(node.SourceLocation, InstructionType.BinaryOperation,
                         node.UnaryOperation == UnaryOperation.PostIncrement || node.UnaryOperation == UnaryOperation.PreIncrement ? (int)BinaryOperation.Addition : (int)BinaryOperation.Subtraction);
                    methodStack.Peek().Instructions.Add(storeInstruction);
                    if (node.UnaryOperation == UnaryOperation.PreDecrement || node.UnaryOperation == UnaryOperation.PreIncrement)
                    {
                        methodStack.Peek().Instructions.Add(loadInstruction);
                    }
                }
                break;
            }
        }
Пример #5
0
        void UnaryOperationVisit(UnaryOperationNode node)
        {
            VariableManager.PushVariableCounter();

            VariableManager.IncrementVariableCounter();
            int t1 = VariableManager.VariableCounter;

            VariableManager.PushVariableCounter();
            node.Operand.Accept(this);

            VariableManager.PopVariableCounter();

            IC.Add(new UnaryOperation(VariableManager.PeekVariableCounter(), t1, node.Symbol));
        }
Пример #6
0
        public void Accept(UnaryOperationNode node)
        {
            switch (node.UnaryOperation)
            {
            case UnaryOperation.Dereference:
                loadLocalPtr(node.SourceLocation, ((IdentifierNode)node.Target).Identifier, "a");
                append("push a");
                break;

            case UnaryOperation.Reference:
                loadLocal(node.SourceLocation, ((IdentifierNode)node.Target).Identifier);
                append("pop a");

                break;
            }
        }
Пример #7
0
        private object Visit(UnaryOperationNode node)
        {
            bool isInteger = node.Value.Data.Type == TokenType.Integer;

            switch (node.Data.Type)
            {
            case TokenType.Add:
                return(isInteger ? +(int)Visit(node.Value) : +(double)Visit(node.Value));

            case TokenType.Sub:
                return(isInteger ? -(int)Visit(node.Value) : -(double)Visit(node.Value));

            default:
                throw new InvalidOperationException($"Token type {node.Data.Type} not expected for unary operations.");
            }
        }
Пример #8
0
        private WhileNode parseWhile()
        {
            var     location = this.location;
            AstNode condition;

            if (acceptToken(TokenType.Identifier, "while"))
            {
                condition = parseExpression();
            }
            else
            {
                expectToken(TokenType.Identifier, "until");
                condition = new UnaryOperationNode(location, parseExpression(), UnaryOperation.LogicalNot);
            }
            AstNode body = parseStatement();

            return(new WhileNode(location, condition, body));
        }
Пример #9
0
        // Parse unary operators (we can count only negative operations).
        private INode ParseUnary()
        {
            var negativeCount = 0;

            while (_tokensSequence.Current.Type == TokenType.Add || _tokensSequence.Current.Type == TokenType.Subtract)
            {
                if (_tokensSequence.Current.Type == TokenType.Subtract)
                {
                    negativeCount++;
                }

                // Skip
                _tokensSequence.MoveNext();
            }

            var node = ParseLeaf();

            if (negativeCount > 0 && negativeCount % 2 != 0)
            {
                node = new UnaryOperationNode(node, n => - n);
            }

            return(node);
        }
 public static string InvalidUseOfOperator(UnaryOperationNode node, TypeInfo operand)
 {
     return($"({node.Line}, {node.Column}) - Semantic Error:" +
            $" Operator '{node.Symbol}' cannot be applied to operator'{operand.Text}'."
            );
 }
Пример #11
0
 public virtual void VisitUnaryOperationNode(UnaryOperationNode node)
 {
     Visit(node.OperatorNode);
     Visit(node.OperandNode);
 }
Пример #12
0
        private static void GenerateUnaryOperation(UnaryOperationNode node, DataContext data)
        {
            Append(data, "(");

            switch (node.Type)
            {
                case UnaryOperationType.Negate:
                    Append(data, "-");
                    break;

                case UnaryOperationType.LogicalNegate:
                    Append(data, "!");
                    break;

                case UnaryOperationType.Increment:
                    Append(data, "++");
                    break;

                case UnaryOperationType.Decrement:
                    Append(data, "--");
                    break;

                default:
                    ThrowUnableToGenerateException("UnaryOperation", node);
                    break;
            }

            GenerateExpression(((UnaryOperationNode)node).ValueExpression, data);
            Append(data, ")");
        }
Пример #13
0
        protected override void DoAction(int action)
        {
#pragma warning disable 162, 1522
            switch (action)
            {
            case 2: // start -> program, Eof
#line 31 "../../kompilator.y"
            {
                YYAccept();
            }
#line default
                break;

            case 3: // start -> error, program, Eof
#line 35 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(1));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 4: // start -> program, error, Eof
#line 41 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 5: // start -> error, Eof
#line 47 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 9: // declaration -> type, Ident, Semicolon
#line 62 "../../kompilator.y"
            {
                if (Compiler.GetVariable(ValueStack[ValueStack.Depth - 2].s_val) == null)
                {
                    Compiler.DeclareVariable(ValueStack[ValueStack.Depth - 3].val_type, ValueStack[ValueStack.Depth - 2].s_val);
                    Compiler.AddNode(new DeclarationNode(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValueStack[ValueStack.Depth - 2].s_val));
                }
                else
                {
                    Compiler.AddError(new VariableAlreadyDeclaredError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 2].s_val));
                }
            }
#line default
                break;

            case 10: // type -> Int
#line 75 "../../kompilator.y"
            { CurrentSemanticValue.val_type = ValType.Int; }
#line default
                break;

            case 11: // type -> Double
#line 76 "../../kompilator.y"
            { CurrentSemanticValue.val_type = ValType.Double; }
#line default
                break;

            case 12: // type -> Bool
#line 77 "../../kompilator.y"
            { CurrentSemanticValue.val_type = ValType.Bool; }
#line default
                break;

            case 13: // statements -> /* empty */
#line 81 "../../kompilator.y"
            {
                Compiler.AddNode(new StatementsBlockNode(Compiler.GetLineNumber()));
            }
#line default
                break;

            case 14: // statements -> statements, statement
#line 85 "../../kompilator.y"
            {
                var innerNode = Compiler.GetNode();
                var blockNode = Compiler.GetNode() as StatementsBlockNode;
                if (blockNode != null)
                {
                    blockNode.AddInnerNode(innerNode);
                    Compiler.AddNode(blockNode);
                }
                else
                {
                    Compiler.AddNode(innerNode);
                }
            }
#line default
                break;

            case 23: // ifStatement -> If, OpenPar, exp, ClosePar, statement
#line 113 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 3].val_type != ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber() - 1, ValueStack[ValueStack.Depth - 3].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }
                else
                {
                    var thenStatement = Compiler.GetNode();
                    var condition     = Compiler.GetNode();

                    Compiler.AddNode(new IfStatementNode(Compiler.GetLineNumber(), condition, thenStatement));
                }
            }
#line default
                break;

            case 24: // ifStatement -> If, OpenPar, exp, ClosePar, statement, Else, statement
#line 128 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 5].val_type != ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 5].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }
                else
                {
                    var elseStatement = Compiler.GetNode();
                    var thenStatement = Compiler.GetNode();
                    var condition     = Compiler.GetNode();

                    Compiler.AddNode(new IfStatementNode(Compiler.GetLineNumber(), condition, thenStatement, elseStatement));
                }
            }
#line default
                break;

            case 25: // whileStatement -> While, OpenPar, exp, ClosePar, statement
#line 146 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 3].val_type != ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }
                else
                {
                    var thenStatement = Compiler.GetNode();
                    var condition     = Compiler.GetNode();

                    Compiler.AddNode(new WhileStatementNode(Compiler.GetLineNumber(), condition, thenStatement));
                }
            }
#line default
                break;

            case 26: // returnStatement -> Return, Semicolon
#line 163 "../../kompilator.y"
            {
                Compiler.AddNode(new ReturnNode(Compiler.GetLineNumber()));
            }
#line default
                break;

            case 27: // readStatement -> Read, Ident, Semicolon
#line 169 "../../kompilator.y"
            {
                if (Compiler.GetVariable(ValueStack[ValueStack.Depth - 2].s_val) == null)
                {
                    Compiler.AddError(new VariableNotDeclaredError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 2].s_val));
                }
                else
                {
                    Compiler.AddNode(new ReadNode(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 2].s_val));
                }
            }
#line default
                break;

            case 28: // readStatement -> Read, error
#line 180 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                yyclearin();
            }
#line default
                break;

            case 29: // readStatement -> Read, error, Eof
#line 186 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 30: // writeStatement -> Write, exp, Semicolon
#line 194 "../../kompilator.y"
            {
                var expNode = Compiler.GetNode();
                Compiler.AddNode(new WriteNode(Compiler.GetLineNumber(), expNode));
            }
#line default
                break;

            case 31: // writeStatement -> Write, Text, Semicolon
#line 199 "../../kompilator.y"
            {
                Compiler.AddNode(new WriteNode(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 2].s_val));
            }
#line default
                break;

            case 32: // writeStatement -> Write, error
#line 203 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                yyclearin();
            }
#line default
                break;

            case 33: // writeStatement -> Write, error, Eof
#line 209 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 34: // expStatement -> exp, Semicolon
#line 217 "../../kompilator.y"
            {
                Compiler.Pop();
            }
#line default
                break;

            case 35: // expStatement -> error
#line 221 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                yyclearin();
            }
#line default
                break;

            case 36: // expStatement -> error, Eof
#line 227 "../../kompilator.y"
            {
                Compiler.AddError(new UnexpectedTokenError(Compiler.GetLineNumber()));
                yyerrok();
                YYAbort();
            }
#line default
                break;

            case 37: // exp -> Ident, Assign, exp
#line 235 "../../kompilator.y"
            {
                var            varType = Compiler.GetVariable(ValueStack[ValueStack.Depth - 3].s_val);
                SyntaxTreeNode right;
                if (varType == null)
                {
                    var error = new VariableNotDeclaredError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].s_val);
                    Compiler.AddError(error);

                    right = Compiler.GetNode();
                    CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
                }
                else if (varType == ValType.Double && ValueStack[ValueStack.Depth - 1].val_type == ValType.Int)
                {
                    // Implicit cast from int to double
                    var tempNode = Compiler.GetNode();

                    CurrentSemanticValue.val_type = varType.Value;
                    right = new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.DoubleCast, tempNode);
                }
                else if (varType.Value != ValueStack[ValueStack.Depth - 1].val_type)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, varType.Value);
                    Compiler.AddError(error);

                    right = Compiler.GetNode();
                    CurrentSemanticValue.val_type = varType.Value;
                }
                else
                {
                    right = Compiler.GetNode();
                    CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
                }

                Compiler.AddNode(new AssignmentNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 3].s_val, right));
            }
#line default
                break;

            case 38: // exp -> logExp
#line 271 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 39: // logOp -> LogOr
#line 276 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.LogOr; }
#line default
                break;

            case 40: // logOp -> LogAnd
#line 277 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.LogAnd; }
#line default
                break;

            case 41: // logExp -> logExp, logOp, relExp
#line 281 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 3].val_type != ValType.Bool && ValueStack[ValueStack.Depth - 3].val_type != ValType.Dynamic)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }
                if (ValueStack[ValueStack.Depth - 1].val_type != ValType.Bool && ValueStack[ValueStack.Depth - 1].val_type != ValType.Dynamic)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }

                CurrentSemanticValue.val_type = ValType.Bool;

                var right = Compiler.GetNode();
                var left  = Compiler.GetNode();
                Compiler.AddNode(new BinaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 2].op_type, left, right));
            }
#line default
                break;

            case 42: // logExp -> relExp
#line 300 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 43: // relOp -> Equal
#line 305 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Equal; }
#line default
                break;

            case 44: // relOp -> NotEqual
#line 306 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.NotEqual; }
#line default
                break;

            case 45: // relOp -> Greater
#line 307 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Greater; }
#line default
                break;

            case 46: // relOp -> GreaterOrEqual
#line 308 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.GreaterOrEqual; }
#line default
                break;

            case 47: // relOp -> Less
#line 309 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Less; }
#line default
                break;

            case 48: // relOp -> LessOrEqual
#line 310 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.LessOrEqual; }
#line default
                break;

            case 49: // relExp -> relExp, relOp, addExp
#line 314 "../../kompilator.y"
            {
                SyntaxTreeNode left;
                SyntaxTreeNode right;
                var            invalidType = false;

                // Allow bools
                if (ValueStack[ValueStack.Depth - 3].val_type == ValType.Bool || ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                {
                    // But only if comparing equality
                    if (ValueStack[ValueStack.Depth - 2].op_type != OpType.Equal && ValueStack[ValueStack.Depth - 2].op_type != OpType.NotEqual)
                    {
                        if (ValueStack[ValueStack.Depth - 3].val_type == ValType.Bool && ValueStack[ValueStack.Depth - 1].val_type != ValType.Bool)
                        {
                            Compiler.AddError(new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValueStack[ValueStack.Depth - 1].val_type));
                            invalidType = true;
                        }
                        else if (ValueStack[ValueStack.Depth - 3].val_type != ValType.Bool && ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                        {
                            Compiler.AddError(new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValueStack[ValueStack.Depth - 3].val_type));
                            invalidType = true;
                        }
                        else
                        {
                            Compiler.AddError(new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Int, ValType.Double));
                            invalidType = true;
                        }
                    }
                    // And both are bool
                    else if (ValueStack[ValueStack.Depth - 3].val_type != ValueStack[ValueStack.Depth - 1].val_type)
                    {
                        Compiler.AddError(new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValueStack[ValueStack.Depth - 1].val_type));
                        invalidType = true;
                    }
                }

                if (!invalidType)
                {
                    CurrentSemanticValue.val_type = ValType.Bool;
                    right = Compiler.GetNode();
                    left  = Compiler.GetNode();
                    Compiler.AddNode(new BinaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 2].op_type, left, right));
                }
            }
#line default
                break;

            case 50: // relExp -> addExp
#line 358 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 51: // addOp -> Plus
#line 363 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Plus; }
#line default
                break;

            case 52: // addOp -> Minus
#line 364 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Minus; }
#line default
                break;

            case 53: // addExp -> addExp, addOp, mulExp
#line 368 "../../kompilator.y"
            {
                var invalidType = false;
                if (ValueStack[ValueStack.Depth - 3].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Int, ValType.Double);
                    Compiler.AddError(error);
                    invalidType = true;
                }
                if (ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Int, ValType.Double);
                    Compiler.AddError(error);
                    invalidType = true;
                }

                if (invalidType)
                {
                    CurrentSemanticValue.val_type = ValType.Int;
                }
                else
                {
                    CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 3].val_type == ValType.Int ? ValueStack[ValueStack.Depth - 1].val_type : ValType.Double;
                }

                var right = Compiler.GetNode();
                var left  = Compiler.GetNode();
                Compiler.AddNode(new BinaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 2].op_type, left, right));
            }
#line default
                break;

            case 54: // addExp -> mulExp
#line 393 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 55: // mulOp -> Multiply
#line 398 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Multiply; }
#line default
                break;

            case 56: // mulOp -> Divide
#line 399 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.Divide; }
#line default
                break;

            case 57: // mulExp -> mulExp, mulOp, bitExp
#line 403 "../../kompilator.y"
            {
                var invalidType = false;
                if (ValueStack[ValueStack.Depth - 3].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Int, ValType.Double);
                    Compiler.AddError(error);
                    invalidType = true;
                }
                if (ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Int, ValType.Double);
                    Compiler.AddError(error);
                    invalidType = true;
                }

                if (invalidType)
                {
                    CurrentSemanticValue.val_type = ValType.Int;
                }
                else
                {
                    CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 3].val_type == ValType.Int ? ValueStack[ValueStack.Depth - 1].val_type : ValType.Double;
                }

                var right = Compiler.GetNode();
                var left  = Compiler.GetNode();
                Compiler.AddNode(new BinaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 2].op_type, left, right));
            }
#line default
                break;

            case 58: // mulExp -> bitExp
#line 428 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 59: // bitOp -> BitOr
#line 433 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.BitOr; }
#line default
                break;

            case 60: // bitOp -> BitAnd
#line 434 "../../kompilator.y"
            { CurrentSemanticValue.op_type = OpType.BitAnd; }
#line default
                break;

            case 61: // bitExp -> bitExp, bitOp, unaryExp
#line 438 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 3].val_type != ValType.Int && ValueStack[ValueStack.Depth - 3].val_type != ValType.Dynamic)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 3].val_type, ValType.Int);
                    Compiler.AddError(error);
                }
                if (ValueStack[ValueStack.Depth - 1].val_type != ValType.Int && ValueStack[ValueStack.Depth - 3].val_type != ValType.Dynamic)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Int);
                    Compiler.AddError(error);
                }

                CurrentSemanticValue.val_type = ValType.Int;

                var right = Compiler.GetNode();
                var left  = Compiler.GetNode();
                Compiler.AddNode(new BinaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 2].op_type, left, right));
            }
#line default
                break;

            case 62: // bitExp -> unaryExp
#line 457 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 63: // unaryExp -> term
#line 463 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 64: // unaryExp -> Minus, unaryExp
#line 467 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Int, ValType.Double);
                    Compiler.AddError(error);
                }

                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;

                var child = Compiler.GetNode();
                Compiler.AddNode(new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.Minus, child));
            }
#line default
                break;

            case 65: // unaryExp -> BitNot, unaryExp
#line 480 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 1].val_type == ValType.Double || ValueStack[ValueStack.Depth - 1].val_type == ValType.Bool)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Int);
                    Compiler.AddError(error);
                }

                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;

                var child = Compiler.GetNode();
                Compiler.AddNode(new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.BitNot, child));
            }
#line default
                break;

            case 66: // unaryExp -> LogNot, unaryExp
#line 493 "../../kompilator.y"
            {
                if (ValueStack[ValueStack.Depth - 1].val_type == ValType.Int || ValueStack[ValueStack.Depth - 1].val_type == ValType.Double)
                {
                    var error = new InvalidTypeError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].val_type, ValType.Bool);
                    Compiler.AddError(error);
                }

                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;

                var child = Compiler.GetNode();
                Compiler.AddNode(new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.LogNot, child));
            }
#line default
                break;

            case 67: // unaryExp -> OpenPar, Int, ClosePar, unaryExp
#line 506 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValType.Int;

                var child = Compiler.GetNode();
                Compiler.AddNode(new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.IntCast, child));
            }
#line default
                break;

            case 68: // unaryExp -> OpenPar, Double, ClosePar, unaryExp
#line 513 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValType.Double;

                var child = Compiler.GetNode();
                Compiler.AddNode(new UnaryOperationNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, OpType.DoubleCast, child));
            }
#line default
                break;

            case 69: // term -> Ident
#line 522 "../../kompilator.y"
            {
                // Throw if variable not declared, else get ValueType
                var varType = Compiler.GetVariable(ValueStack[ValueStack.Depth - 1].s_val);
                if (varType == null)
                {
                    var error = new VariableNotDeclaredError(Compiler.GetLineNumber(), ValueStack[ValueStack.Depth - 1].s_val);
                    Compiler.AddError(error);

                    varType = ValType.Dynamic;
                }

                CurrentSemanticValue.val_type = varType.Value;
                Compiler.AddNode(new VariableNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 1].s_val));
            }
#line default
                break;

            case 70: // term -> const
#line 537 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 1].val_type;
            }
#line default
                break;

            case 71: // term -> OpenPar, exp, ClosePar
#line 541 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValueStack[ValueStack.Depth - 2].val_type;
            }
#line default
                break;

            case 72: // const -> IntValue
#line 547 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValType.Int;
                Compiler.AddNode(new ConstantNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 1].i_val));
            }
#line default
                break;

            case 73: // const -> DoubleValue
#line 552 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValType.Double;
                Compiler.AddNode(new ConstantNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 1].d_val));
            }
#line default
                break;

            case 74: // const -> BoolValue
#line 557 "../../kompilator.y"
            {
                CurrentSemanticValue.val_type = ValType.Bool;
                Compiler.AddNode(new ConstantNode(Compiler.GetLineNumber(), CurrentSemanticValue.val_type, ValueStack[ValueStack.Depth - 1].b_val));
            }
#line default
                break;
            }
#pragma warning restore 162, 1522
        }
Пример #14
0
        private string GetExpression(UnaryOperationNode unaryOp, IDictionary <IFixing, string> fixingRefs)
        {
            var argExpression = GetExpressionBase(unaryOp.Argument, fixingRefs);

            return(unaryOp.OpSymbol + "(" + argExpression + ")");
        }
Пример #15
0
 public virtual void VisitUnaryOperationNode(UnaryOperationNode node)
 {
     Visit(node.OperatorNode);
     Visit(node.OperandNode);
 }
Пример #16
0
        public override DynValue Visit(UnaryOperationNode unaryOperationNode)
        {
            var operand = Visit(unaryOperationNode.Operand);

            switch (unaryOperationNode.Type)
            {
            case UnaryOperationType.Plus:
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt to apply unary + on {operand.Type}.",
                                               unaryOperationNode.Line);
                }

                return(new DynValue(operand.Number));

            case UnaryOperationType.Minus:
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt to apply unary - on {operand.Type}.",
                                               unaryOperationNode.Line);
                }

                return(new DynValue(-operand.Number));

            case UnaryOperationType.Length:
            {
                switch (operand.Type)
                {
                case DynValueType.String:
                    return(new DynValue(operand.String.Length));

                case DynValueType.Table:
                    return(new DynValue(operand.Table.Count));

                default:
                    throw new RuntimeException($"Attempt to retrieve the length of {operand.Type}.",
                                               unaryOperationNode.Line);
                }
            }

            case UnaryOperationType.ToString:
                return(operand.AsString());

            case UnaryOperationType.NameOf:
                if (unaryOperationNode.Operand is VariableNode variable)
                {
                    return(new DynValue(variable.Identifier));
                }

                throw new RuntimeException("Attempt to get a name of a non-variable symbol.",
                                           unaryOperationNode.Line);

            case UnaryOperationType.Negation:
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt to invert a {operand.Type}.", unaryOperationNode.Line);
                }

                if (operand.Number != 0)
                {
                    return(new DynValue(0));
                }
                else
                {
                    return(new DynValue(1));
                }

            case UnaryOperationType.BitwiseNot:
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt to negate a {operand.Type}.", unaryOperationNode.Line);
                }

                return(new DynValue(~(long)operand.Number));

            case UnaryOperationType.Floor:
                if (operand.Type != DynValueType.Number)
                {
                    throw new RuntimeException($"Attempt to retrieve floor value of {operand.Type}.",
                                               unaryOperationNode.Line);
                }

                return(new DynValue(decimal.Floor(operand.Number)));

            default: throw new RuntimeException("Unknown unary operation type.", unaryOperationNode.Line);
            }
        }
Пример #17
0
    public override string GenCode()
    {
        // Implicit cast int -> double
        // Generate fake node with explicit cast
        SyntaxTreeNode tempNode;

        if (Left.Type == ValType.Int && Right.Type == ValType.Double)
        {
            tempNode = new UnaryOperationNode(LineNo, ValType.Double, OpType.DoubleCast, Left);
            Left     = tempNode;
        }
        else if (Left.Type == ValType.Double && Right.Type == ValType.Int)
        {
            tempNode = new UnaryOperationNode(LineNo, ValType.Double, OpType.DoubleCast, Right);
            Right    = tempNode;
        }

        // Optimize calculations in those cases - done in switch below
        if (OperatorType != OpType.LogOr && OperatorType != OpType.LogAnd)
        {
            Left?.GenCode();
            Right?.GenCode();
        }

        string text       = "";
        var    helperNode = new UnaryOperationNode(-1, ValType.Bool, OpType.LogNot, null);

        switch (OperatorType)
        {
        case OpType.LogOr:
            var falseLabel = Compiler.GenerateLabel();
            var trueLabel  = Compiler.GenerateLabel();
            var endLabel   = Compiler.GenerateLabel();
            Left.GenCode();
            Compiler.EmitCode($"brtrue {trueLabel}");
            Right.GenCode();
            Compiler.EmitCode($"brtrue {trueLabel}");
            Compiler.EmitCode("ldc.i4.0", true, falseLabel);
            Compiler.EmitCode($"br {endLabel}");
            Compiler.EmitCode("ldc.i4.1", true, trueLabel);
            Compiler.EmitCode("nop", true, endLabel);
            break;

        case OpType.LogAnd:
            falseLabel = Compiler.GenerateLabel();
            trueLabel  = Compiler.GenerateLabel();
            endLabel   = Compiler.GenerateLabel();
            Left.GenCode();
            Compiler.EmitCode($"brfalse {falseLabel}");
            Right.GenCode();
            Compiler.EmitCode($"brtrue {trueLabel}");
            Compiler.EmitCode("ldc.i4.0", true, falseLabel);
            Compiler.EmitCode($"br {endLabel}");
            Compiler.EmitCode("ldc.i4.1", true, trueLabel);
            Compiler.EmitCode("nop", true, endLabel);
            break;

        case OpType.Equal:
            text = "ceq";
            break;

        case OpType.NotEqual:
            // Check for equality
            // And negate stack top (equality result)
            Compiler.EmitCode("ceq");
            helperNode.GenCode();
            break;

        case OpType.Greater:
            text = "cgt";
            break;

        case OpType.GreaterOrEqual:
            // Check for less
            // And negate stack top (less result)
            Compiler.EmitCode("clt");
            helperNode.GenCode();
            break;

        case OpType.Less:
            text = "clt";
            break;

        case OpType.LessOrEqual:
            // Check for greater
            // And negate stack top (greater result)
            Compiler.EmitCode("cgt");
            helperNode.GenCode();
            break;

        case OpType.Plus:
            text = "add";
            break;

        case OpType.Minus:
            text = "sub";
            break;

        case OpType.Multiply:
            text = "mul";
            break;

        case OpType.Divide:
            text = "div";
            break;

        case OpType.BitOr:
            text = "or";
            break;

        case OpType.BitAnd:
            text = "and";
            break;

        default:
            Compiler.AddError(new UndefinedRuntimeError(LineNo));
            break;
        }

        Compiler.EmitCode(text);
        if (GenPop)
        {
            Compiler.EmitCode("pop", true);
        }

        return(text);
    }
Пример #18
0
 private void Visit(UnaryOperationNode node) => Visit(node.Expression);
Пример #19
0
 public abstract DynValue Visit(UnaryOperationNode unaryOperationNode);
Пример #20
0
 public static string InvalidUseOfOperator(UnaryOperationNode node, TypeInfo operand)
 {
     return($"(Line: {node.Line}, Column: {node.Column})" +
            $" Operator '{node.Symbol}' cannot be applied to operands of type '{operand.Text}'."
            );
 }
Пример #21
0
 /// <summary>
 /// 一元操作符
 /// </summary>
 /// <param name="node"></param>
 public void Visit(UnaryOperationNode node)
 {
     Visit((Object)node.OperationType);
 }
Пример #22
0
 private void Visit(UnaryOperationNode node)
 {
     Visit(node.Value);
 }