# encoding: utf-8 # frozen_string_literal: true require "carbon/compiler/visitor/generation/expressions/assignment" require "carbon/compiler/visitor/generation/expressions/calls" module Carbon module Compiler module Visitor class Generation module Expressions include Generation::Expressions::Assignment include Generation::Expressions::Calls Generation.on Node::Expression::Literal => :visit_expression_literal def visit_expression_literal(node, context) Tacky::Typed.new(node.value, node.type) end # TODO: implement short circuitry Generation.on Node::Expression::Operation::And => :visit_expression_operation_and def visit_expression_operation_and(node, context) context.build do |b| left = accept(node.left, context) assert_type_boolean(left.type, location: node.left.location) lchk = b.icmp(:ne, left, 0).as(Carbon::Boolean) right = accept(node.right, context) assert_type_boolean(right.type, location: node.right.location) rchk = b.icmp(:ne, right, 0).as(Carbon::Boolean) b.and(lchk, rchk).as(Carbon::Boolean) end end Generation.on Node::Expression::Operation::Or => :visit_expression_operation_or def visit_expression_operation_or(node, context) context.build do |b| left = accept(node.left, context) assert_type_boolean(left.type, location: node.left.location) lchk = b.icmp(:ne, left, 0).as(Carbon::Boolean) right = accept(node.right, context) assert_type_boolean(left.right, location: node.right.location) rchk = b.icmp(:ne, right, 0).as(Carbon::Boolean) b.or(lchk, rchk).as(Carbon::Boolean) end end Generation.on Node::Expression::Operation::Neq => :visit_expression_operation_neq def visit_expression_operation_neq(node, context) context.build do |b| left = accept(node.left, context) right = accept(node.right, context) name = left.type.call(:==, [left.type, right.type]) result = b.call(name, left, right).as(Carbon::Boolean) context.type(b.xor(result, 1), Carbon::Boolean) end end Generation.on Node::Expression::Operation::Normal => :visit_expression_operation_normal def visit_expression_operation_normal(node, context) context.build do |b| left = accept(node.left, context) right = accept(node.right, context) name = left.type.call(node.op.value, [left.type, right.type]) type = context.find(name).return b.call(name, left, right).as(type) end end Generation.on Node::Name => :visit_name def visit_name(node, context) value = context.current.fetch(node.value) context.build.load(value).as(value.type) end end end end end end