diff options
Diffstat (limited to 'Compiler/visitors/Operations.cs')
| -rw-r--r-- | Compiler/visitors/Operations.cs | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/Compiler/visitors/Operations.cs b/Compiler/visitors/Operations.cs new file mode 100644 index 0000000..8483747 --- /dev/null +++ b/Compiler/visitors/Operations.cs @@ -0,0 +1,305 @@ +namespace Q1.Compiler.visitors; + +public partial class CCompilerVisitor +{ + private void BaseBinaryOperation(CGrammarParser.ExpressionContext leftExpr, CGrammarParser.ExpressionContext rightExpr, string operation, string operationFriendlyName) + { + string left = this.VisitExpression(leftExpr); + + this.Instruction($"push {left}", "left operand"); + + string right = this.VisitExpression(rightExpr); + + this.Instruction($"mov {right}, V1", "right operand"); + this.Instruction($"pop V0", "get left operand back"); + this.Instruction($"{operation} V0, V1", $"compute {operationFriendlyName}"); + } + + private string BaseBinaryCompoundOperation(CGrammarParser.TargetContext leftTarget, CGrammarParser.ExpressionContext rightExpr, string operation, string operationFriendlyName, string operationOutput) + { + Target left = this.VisitTarget(leftTarget); + + this.Instruction($"push {left.Value}", "left operand"); + + string? right = this.VisitExpression(rightExpr); + if (right == null) + throw new CompilerException($"Right operand for {operationFriendlyName} was not an expression."); + + this.Instruction($"mov {right}, V1", "right operand"); + this.Instruction($"pop V0", "get left operand back"); + this.Instruction($"{operation} V0, V1", $"compute {operationFriendlyName}"); + + this.Instruction($"push {operationOutput}", "computation results"); + + left = this.VisitTarget(leftTarget); + this.Instruction("pop V1", "get computation results back"); + this.DynamicMove(left.Type, "V1", left.Value, "store back into left param"); + + return left.Value; + } + + public override string VisitNotExpression(CGrammarParser.NotExpressionContext context) + { + string value = this.VisitExpression(context.expression()); + + this.Instruction($"not {value}"); + return "LX"; + } + public override string VisitInvertExpression(CGrammarParser.InvertExpressionContext context) + { + string value = this.VisitExpression(context.expression()); + + this.Instruction($"inv {value}"); + return "DX"; + } + public override string VisitAddExpression(CGrammarParser.AddExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "add", "addition"); + return "AX"; + } + public override string VisitSubtractExpression(CGrammarParser.SubtractExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "sub", "subtraction"); + return "AX"; + } + public override string VisitMultiplyExpression(CGrammarParser.MultiplyExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "mul", "multiplication"); + return "AX"; + } + public override string VisitDivideExpression(CGrammarParser.DivideExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "div", "division"); + return "AX"; + } + public override string VisitModulusExpression(CGrammarParser.ModulusExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "mod", "modulus"); + return "AX"; + } + public override string VisitEqualExpression(CGrammarParser.EqualExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "cmp", "equality check"); + return "LX"; + } + public override string VisitNotEqualExpression(CGrammarParser.NotEqualExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "cmp", "inequality check"); + this.Instruction($"not"); // lx is implicit + return "LX"; + } + public override string VisitGreaterThanExpression(CGrammarParser.GreaterThanExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "gt", "greater than check"); + return "LX"; + } + public override string VisitLessThanExpression(CGrammarParser.LessThanExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "lt", "less than check"); + return "LX"; + } + public override string VisitLogicalOrExpression(CGrammarParser.LogicalOrExpressionContext context) + { + string left = this.VisitExpression(context.left); + + string clauseBranch = this.GenerateBranchLabel("clause"); + string endBranch = this.GenerateBranchLabel("end"); + + this.Instruction($"cmp {left}, 0", "logical or"); + this.Instruction("bz"); // implicit LX + this.Instruction($"jmp {clauseBranch}"); // only if bz is not 0 + this.Instruction("mov 1, V0", "first operand succeeded, store 1 and skip second operand"); + this.Instruction($"jmp {endBranch}"); + this.Branch(clauseBranch); + + string right = this.VisitExpression(context.right); + + this.Instruction($"cmp {right}, 0", "compare result from second operand to 0"); + this.Instruction("not"); + this.Instruction("mov LX, V0", "store second operand result"); + this.Branch(endBranch); + + return "V0"; + } + public override string VisitLogicalAndExpression(CGrammarParser.LogicalAndExpressionContext context) + { + string left = this.VisitExpression(context.left); + + string clauseBranch = this.GenerateBranchLabel("clause"); + string endBranch = this.GenerateBranchLabel("end"); + + this.Instruction($"cmp {left}, 0", "logical and"); + this.Instruction("not"); + this.Instruction("bz"); // implicit LX + this.Instruction($"jmp {clauseBranch}"); // only if bz is not 0 + this.Instruction("mov 0, V0", "first operand failed, store 0 and skip second"); + this.Instruction($"jmp {endBranch}"); + this.Branch(clauseBranch); + + string right = this.VisitExpression(context.right); + + this.Instruction($"cmp {right}, 0", "compare result from second operand to 0"); + this.Instruction("not"); + this.Instruction("mov LX, V0", "store second operand result"); + this.Branch(endBranch); + + return "V0"; + } + public override string VisitGreaterThanOrEqualExpression(CGrammarParser.GreaterThanOrEqualExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "cmp", "equality check"); + string endBranch = this.GenerateBranchLabel("end"); + + this.Instruction("bz"); + this.Instruction($"jmp {endBranch}"); + this.Instruction($"gt V0, V1"); + this.Branch(endBranch); + + return "LX"; + } + public override string VisitLessThanOrEqualExpression(CGrammarParser.LessThanOrEqualExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "cmp", "equality check"); + string endBranch = this.GenerateBranchLabel("end"); + + this.Instruction("bz"); + this.Instruction($"jmp {endBranch}"); + this.Instruction($"lt V0, V1"); + this.Branch(endBranch); + + return "LX"; + } + public override string VisitBitwiseXorExpression(CGrammarParser.BitwiseXorExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "xor", "exclusive or"); + return "DX"; + } + public override string VisitBitwiseOrExpression(CGrammarParser.BitwiseOrExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "or", "or"); + return "DX"; + } + public override string VisitBitwiseAndExpression(CGrammarParser.BitwiseAndExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "and", "and"); + return "DX"; + } + public override string VisitBitwiseLeftShiftExpression(CGrammarParser.BitwiseLeftShiftExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "shl", "left shift"); + return "DX"; + } + public override string VisitBitwiseRightShiftExpression(CGrammarParser.BitwiseRightShiftExpressionContext context) + { + this.BaseBinaryOperation(context.left, context.right, "shr", "right shift"); + return "DX"; + } + public override string VisitCompoundAddExpression(CGrammarParser.CompoundAddExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "add", + "addition", + "AX"); + } + public override string VisitCompoundSubtractExpression(CGrammarParser.CompoundSubtractExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "sub", + "subtraction", + "AX"); + } + public override string VisitCompoundMultiplyExpression(CGrammarParser.CompoundMultiplyExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "mul", + "multiplication", + "AX"); + } + public override string VisitCompoundDivideExpression(CGrammarParser.CompoundDivideExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "div", + "division", + "AX"); + } + public override string VisitCompoundModulusExpression(CGrammarParser.CompoundModulusExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "mod", + "modulus", + "AX"); + } + public override string VisitCompoundBitwiseOrExpression(CGrammarParser.CompoundBitwiseOrExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "or", + "or", + "DX"); + } + public override string VisitCompoundBitwiseXorExpression(CGrammarParser.CompoundBitwiseXorExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "xor", + "exclusive or", + "DX"); + } + public override string VisitCompoundBitwiseAndExpression(CGrammarParser.CompoundBitwiseAndExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "and", + "and", + "DX"); + } + public override string VisitCompoundBitwiseLeftShiftExpression(CGrammarParser.CompoundBitwiseLeftShiftExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "shl", + "left shift", + "DX"); + } + public override string VisitCompoundBitwiseRightShiftExpression(CGrammarParser.CompoundBitwiseRightShiftExpressionContext context) + { + return this.BaseBinaryCompoundOperation(context.target(), + context.expression(), + "shr", + "right shift", + "DX"); + } + public override string VisitIncrementPrefixExpression(CGrammarParser.IncrementPrefixExpressionContext context) + { + Target target = this.VisitTarget(context.target()); + this.Instruction($"inc {target.Value}", "++i"); + return target.Value; + } + public override string VisitDecrementPrefixExpression(CGrammarParser.DecrementPrefixExpressionContext context) + { + Target target = this.VisitTarget(context.target()); + this.Instruction($"dec {target.Value}", "--i"); + return target.Value; + } + public override string VisitIncrementPostfixExpression(CGrammarParser.IncrementPostfixExpressionContext context) + { + Target target = this.VisitTarget(context.target()); + this.Instruction($"push {target.Value}", "i++"); + this.Instruction($"inc {target.Value}"); + this.Instruction("pop V0"); + return "V0"; + } + public override string VisitDecrementPostfixExpression(CGrammarParser.DecrementPostfixExpressionContext context) + { + Target target = this.VisitTarget(context.target()); + this.Instruction($"push {target.Value}", "i--"); + this.Instruction($"dec {target.Value}"); + this.Instruction($"pop V0"); + return "V0"; + } +}
\ No newline at end of file |
