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(); }
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); } }
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; } }
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)); }
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; } }
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."); } }
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)); }
// 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}'." ); }
public virtual void VisitUnaryOperationNode(UnaryOperationNode node) { Visit(node.OperatorNode); Visit(node.OperandNode); }
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, ")"); }
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 }
private string GetExpression(UnaryOperationNode unaryOp, IDictionary <IFixing, string> fixingRefs) { var argExpression = GetExpressionBase(unaryOp.Argument, fixingRefs); return(unaryOp.OpSymbol + "(" + argExpression + ")"); }
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); } }
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); }
private void Visit(UnaryOperationNode node) => Visit(node.Expression);
public abstract DynValue Visit(UnaryOperationNode unaryOperationNode);
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}'." ); }
/// <summary> /// 一元操作符 /// </summary> /// <param name="node"></param> public void Visit(UnaryOperationNode node) { Visit((Object)node.OperationType); }
private void Visit(UnaryOperationNode node) { Visit(node.Value); }