def visitExpressionMultiplicative( self, ctx: LanguageParser.ExpressionMultiplicativeContext): if ctx.MUL_OP() or ctx.DIV_OP() or ctx.MOD_OP() or ctx.EXP_OP(): operand_one = self.visitExpressionMultiplicative( ctx.expressionMultiplicative()) operand_two = self.visitExpressionUnary(ctx.expressionUnary()) if operand_one.type is not Type.NUMBER or operand_two.type is not Type.NUMBER: raise exceptions.TypeMismatchException( "The multiplicative operators can only be applied to values of type NUMBER." ) if ctx.MUL_OP(): result = operand_one.value * operand_two.value elif ctx.DIV_OP(): result = operand_one.value / operand_two.value elif ctx.MOD_OP(): result = operand_one.value % operand_two.value elif ctx.EXP_OP(): result = operand_one.value**operand_two.value else: raise Exception() return Value(Type.NUMBER, result) return self.visitExpressionUnary(ctx.expressionUnary())
def visitExpressionRelational( self, ctx: LanguageParser.ExpressionRelationalContext): expression_additive = ctx.expressionAdditive() if ctx.LT_OP() or ctx.GT_OP() or ctx.LTOE_OP() or ctx.GTOE_OP(): operand_one = self.visitExpressionRelational( ctx.expressionRelational()) operand_two = self.visitExpressionAdditive(expression_additive) if operand_one.type is not Type.NUMBER or operand_two.type is not Type.NUMBER: raise exceptions.TypeMismatchException( "The relational operators can only be applied to values of type NUMBER." ) if ctx.LT_OP(): result = operand_one.value < operand_two.value elif ctx.GT_OP(): result = operand_one.value > operand_two.value elif ctx.LTOE_OP(): result = operand_one.value <= operand_two.value elif ctx.GTOE_OP(): result = operand_one.value >= operand_two.value else: raise Exception() return Value(Type.BOOL, result) return self.visitExpressionAdditive(expression_additive)
def visitExpressionAdditive(self, ctx: LanguageParser.ExpressionAdditiveContext): if ctx.ADD_OP() or ctx.SUB_OP(): operand_one = self.visitExpressionAdditive( ctx.expressionAdditive()) operand_two = self.visitExpressionMultiplicative( ctx.expressionMultiplicative()) if operand_one.type != operand_two.type: raise exceptions.TypeMismatchException( "The additive operators must be applied to values of the same types.", None, operand_one.type, operand_two.type) # Numbers if operand_one.type is Type.NUMBER: if ctx.ADD_OP(): return Value(Type.NUMBER, operand_one.value + operand_two.value) else: # SUB return Value(Type.NUMBER, operand_one.value - operand_two.value) if operand_one.type is Type.STRING: if ctx.ADD_OP(): return Value(Type.STRING, operand_one.value + operand_two.value) else: raise Exception("Unsupported string - string") return self.visitExpressionMultiplicative( ctx.expressionMultiplicative())
def execute(self, arguments): list = arguments[0] if list.type != Type.LIST: raise exceptions.TypeMismatchException( "list_push must be called on list.", None, list.type, Type.LIST) for to_push in arguments[1:]: list.value.append(to_push)
def visitStatementAssignmentBracket( self, ctx: LanguageParser.StatementAssignmentBracketContext): subject = self.visitExpressionPrimary(ctx.expressionPrimary()) index = self.visitExpression( ctx.expressionBracketAccess().expression()) to_assign = self.visitExpression(ctx.expression()) if subject.type != Type.LIST and subject.type != Type.MAP: raise exceptions.TypeMismatchException( "[] applied to invalid value.") if subject.type == Type.LIST and index.type != Type.NUMBER: raise exceptions.TypeMismatchException("List index must be number", None, index.type, Type.Number) if subject.type == Type.LIST: subject.value[int(index.value)] = to_assign else: subject.value[index.value] = to_assign
def visitExpressionOr(self, ctx: LanguageParser.ExpressionOrContext): if ctx.OR_OP() is not None: operand_one = self.visitExpressionOr(ctx.expressionOr()) operand_two = self.visitExpressionAnd(ctx.expressionAnd()) if operand_one.type is not Type.BOOL or operand_two.type is not Type.BOOL: raise exceptions.TypeMismatchException( "The or operator (||) can only be applied to values of type BOOL.", []) return Value(Type.BOOL, operand_one.value or operand_two.value) return self.visitExpressionAnd(ctx.expressionAnd())
def visitExpressionUnary(self, ctx: LanguageParser.ExpressionUnaryContext): if ctx.NOT_OP(): operand = self.visitExpressionPrimary(ctx.expressionPrimary()) if operand.type is not Type.BOOL: raise exceptions.TypeMismatchException( "The not operator (!) can only be applied to values of type BOOL." ) return Value(Type.BOOL, not operand.value) if ctx.TYPE(): operand = self.visitExpressionPrimary(ctx.expressionPrimary()) return Value(Type.STRING, operand.get_type_name()) if ctx.DEC_OP(): operand = self.visitExpressionPrimary(ctx.expressionPrimary()) if operand.type is not Type.NUMBER: raise exceptions.TypeMismatchException( "The not dec (--) can only be applied to values of type NUMBER." ) operand.value = operand.value - 1 return operand if ctx.INC_OP(): operand = self.visitExpressionPrimary(ctx.expressionPrimary()) if operand.type is not Type.NUMBER: raise exceptions.TypeMismatchException( "The not dec (++) can only be applied to values of type NUMBER." ) operand.value = operand.value + 1 return operand return self.visitExpressionPrimary(ctx.expressionPrimary())
def visitStatementIf(self, ctx: LanguageParser.StatementIfContext): conditional = self.visitExpression(ctx.expression()) if conditional.type is not Type.BOOL: raise exceptions.TypeMismatchException( "If conditions must be type boolean", None, conditional.type, Type.BOOL) try: self._stack.push(Frame()) if conditional.value: return self.visitCodeBlock(ctx.codeBlock()) elif ctx.statementElse() is not None: return self.visitCodeBlock(ctx.statementElse().codeBlock()) finally: self._stack.pop()
def visitStatementWhile(self, ctx: LanguageParser.StatementWhileContext): self._stack.push(Frame()) try: while True: conditional = self.visitExpression(ctx.expression()) if conditional.type is not Type.BOOL: raise exceptions.TypeMismatchException( "If conditions must be type boolean", None, conditional.type, Type.BOOL) if conditional.value: ret = self.visitCodeBlock(ctx.codeBlock()) if ret is not None: return ret else: return None finally: self._stack.pop()
def visitStatementFor(self, ctx: LanguageParser.StatementForContext): self.visitStatementVariableDeclaration( ctx.statementVariableDeclaration()) ret = Value(Type.NULL, None) while True: conditional = self.visitExpression( ctx.statementExpression().expression()) if conditional.type is not Type.BOOL: raise exceptions.TypeMismatchException( "For conditions must be type boolean", None, conditional.type, Type.BOOL) if conditional.value: ret = self.visitCodeBlock(ctx.codeBlock()) if ret is not None: ret = ret break self.visitExpression(ctx.expression()) else: break return ret
def visitExpressionPrimary(self, ctx: LanguageParser.ExpressionPrimaryContext): expression_paren = ctx.expressionParenthesized() if expression_paren is not None: return self.visitExpressionParenthesized(expression_paren) expression_func = ctx.expressionFunction() if expression_func is not None: return self.visitExpressionFunction(expression_func) expression_var = ctx.expressionVariable() if expression_var is not None: return self.visitExpressionVariable(expression_var) expression_list = ctx.expressionList() if expression_list is not None: return self.visitExpressionList(expression_list) expression_map = ctx.expressionMap() if expression_map is not None: return self.visitExpressionMap(expression_map) expression_lit = ctx.expressionLiteral() if expression_lit is not None: return self.visitExpressionLiteral(expression_lit) expression_closure = ctx.expressionClosure() if expression_closure is not None: return self.visitExpressionClosure(expression_closure) field_access = ctx.expressionFieldAccess() if field_access is not None: field_name = field_access.IDENTIFIER().getText() subject = self.visitExpressionPrimary(ctx.expressionPrimary()) field_value = subject.fields.get(field_name) if field_value is None: raise exceptions.UnknownFieldException(subject, field_name) return field_value closure_invocation = ctx.expressionClosureInvocation() if closure_invocation is not None: subject = self.visitExpressionPrimary(ctx.expressionPrimary()) closure = subject.value if subject.type != Type.CLOSURE: raise exceptions.TypeMismatchException( "Cannot only use .() operator on CLOSURE.", None, subject.type, Type.CLOSURE) arguments = map( lambda expression: self.visitExpression(expression), closure_invocation.arguments().expression()) new_frame = Frame() new_frame.set_variables(zip(closure.parameters, arguments)) self._stack.push(new_frame) if closure.expression is not None: result = self.visitExpression(closure.expression) else: result = self.run_returnable(closure.statements) self._stack.pop() return result method_access = ctx.expressionMethodAccess() if method_access is not None: method_name = method_access.IDENTIFIER().getText() subject = self.visitExpressionPrimary(ctx.expressionPrimary()) method_instance = subject.methods.get(method_name) if method_instance is None: raise exceptions.UnknownMethodException(subject, method_name) arguments = map( lambda expression: self.visitExpression(expression), method_access.arguments().expression()) new_frame = Frame() new_frame.set_variables(zip(method_instance.parameters, arguments)) new_frame.set_variable("this", subject) self._stack.push(new_frame) result = self.visitCodeBlock(method_instance.code) self._stack.pop() return result new_expression = ctx.expressionNew() if new_expression is not None: return self.visitExpressionNew(new_expression) bracket_access = ctx.expressionBracketAccess() if bracket_access is not None: subject = self.visitExpressionPrimary(ctx.expressionPrimary()) if subject.type != Type.LIST and subject.type != Type.MAP: raise exceptions.TypeMismatchException( "[] applied to invalid value.") index = self.visitExpression(bracket_access.expression()) if subject.type == Type.LIST and index.type != Type.NUMBER: raise exceptions.TypeMismatchException( "List index must be number", None, index.type, Type.Number) if subject.type == Type.LIST: value = subject.value[int(index.value)].value else: temp = subject.value.get(index.value) value = temp and temp.value return Value(get_type_of(value), value)