Class: Idl::UnaryOperatorExpressionAst
- Includes:
- Rvalue
- Defined in:
- lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb
Overview
represents a unary operator
for example:
-value
~value
!bool_variable
Constant Summary
Constants inherited from AstNode
AstNode::Bits1Type, AstNode::Bits32Type, AstNode::Bits64Type, AstNode::BoolType, AstNode::ConstBoolType, AstNode::PossiblyUnknownBits1Type, AstNode::PossiblyUnknownBits32Type, AstNode::PossiblyUnknownBits64Type, AstNode::ReachableFunctionCacheType, AstNode::StringType, AstNode::VoidType
Instance Attribute Summary
Attributes inherited from AstNode
#children, #input, #interval, #parent
Class Method Summary collapse
Instance Method Summary collapse
- #const_eval?(symtab) ⇒ Boolean
-
#exp ⇒ AstNode
The operated-on expression.
- #expression ⇒ Object
- #gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
-
#initialize(input, interval, op, expression) ⇒ UnaryOperatorExpressionAst
constructor
A new instance of UnaryOperatorExpressionAst.
- #invert(symtab) ⇒ Object
-
#op ⇒ String
The operator.
- #prune(symtab, forced_type: nil) ⇒ Object
- #to_h ⇒ Object
- #to_idl ⇒ Object
-
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
-
#type_check(symtab, strict:) ⇒ void
type check this node and all children.
-
#value(symtab) ⇒ Object
Return the compile-time-known value of the node.
Methods included from Rvalue
#max_value, #min_value, #truncate, #values
Methods inherited from AstNode
#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_dst_registers, #find_referenced_csrs, #find_src_registers, #freeze_tree, #gen_option_adoc, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #nullify_assignments, #pass_find_return_values, #path, #print_ast, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested
Constructor Details
#initialize(input, interval, op, expression) ⇒ UnaryOperatorExpressionAst
Returns a new instance of UnaryOperatorExpressionAst.
6192 6193 6194 6195 6196 6197 |
# File 'lib/idlc/ast.rb', line 6192 def initialize(input, interval, op, expression) super(input, interval, [expression]) raise "Bad op #{op.inspect}" unless ["~", "!", "-"].include?(op) @op = op end |
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 |
# File 'lib/idlc/ast.rb', line 6304 def self.from_h(yaml, source_mapper) raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "unary_operator_expr" input = input_from_source_yaml(yaml.fetch("source"), source_mapper) interval = interval_from_source_yaml(yaml.fetch("source")) UnaryOperatorExpressionAst.new( input, interval, yaml.fetch("op"), AstNode.from_h(yaml.fetch("expr"), source_mapper) ) end |
Instance Method Details
#const_eval?(symtab) ⇒ Boolean
6188 |
# File 'lib/idlc/ast.rb', line 6188 def const_eval?(symtab) = expression.const_eval?(symtab) |
#exp ⇒ AstNode
Returns the operated-on expression.
6282 6283 6284 |
# File 'lib/idlc/ast.rb', line 6282 def exp expression end |
#expression ⇒ Object
6190 |
# File 'lib/idlc/ast.rb', line 6190 def expression = @children[0] |
#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
270 271 272 |
# File 'lib/idlc/passes/gen_adoc.rb', line 270 def gen_adoc(indent = 0, indent_spaces: 2) "#{' ' * indent}#{op}#{exp.gen_adoc(0, indent_spaces:)}" end |
#invert(symtab) ⇒ Object
6199 6200 6201 6202 6203 6204 6205 6206 6207 |
# File 'lib/idlc/ast.rb', line 6199 def invert(symtab) unless symtab.nil? type_error "Not a boolean operator" unless type(symtab).kind == :boolean end type_error "Invert only works with !" unless op == "!" expression end |
#op ⇒ String
Returns The operator.
6287 6288 6289 |
# File 'lib/idlc/ast.rb', line 6287 def op @op end |
#prune(symtab, forced_type: nil) ⇒ Object
791 792 793 794 795 796 797 798 799 800 801 802 803 804 |
# File 'lib/idlc/passes/prune.rb', line 791 def prune(symtab, forced_type: nil) value_result = value_try do v = value(symtab) if type(symtab).kind == :bits if type(symtab).width == :unknown value_error "Unknown width" end end return PruneHelpers.create_literal(symtab, v, type(symtab), forced_type: forced_type || type(symtab)) end value_else(value_result) do UnaryOperatorExpressionAst.new(input, interval, @op, exp.prune(symtab, forced_type:)) end end |
#to_h ⇒ Object
6296 6297 6298 6299 6300 6301 |
# File 'lib/idlc/ast.rb', line 6296 def to_h = { "kind" => "unary_operator_expr", "op" => op, "expr" => expression.to_h, "source" => source_yaml } |
#to_idl ⇒ Object
6293 |
# File 'lib/idlc/ast.rb', line 6293 def to_idl = "#{op}#{expression.to_idl}" |
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
Should not be called until #type_check is called with the same arguments
6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 |
# File 'lib/idlc/ast.rb', line 6210 def type(symtab) case op when "-", "~" exp.type(symtab).clone when "!" if exp.type(symtab).const? ConstBoolType else BoolType end else internal_error "unhandled op #{op}" end end |
#type_check(symtab, strict:) ⇒ void
6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 |
# File 'lib/idlc/ast.rb', line 6226 def type_check(symtab, strict:) exp.type_check(symtab, strict:) case op when "-" unless [:bits, :bitfield].include?(exp.type(symtab).kind) type_error "#{exp.type(symtab)} does not support unary #{op} operator" end # type_error "Unary minus only works on signed values" unless exp.type(symtab).signed? when "~" unless [:bits, :bitfield].include?(exp.type(symtab).kind) type_error "#{exp.type(symtab)} does not support unary #{op} operator" end when "!" unless exp.type(symtab).convertable_to?(:boolean) if exp.type(symtab).kind == :bits type_error "#{exp.type(symtab)} does not support unary #{op} operator. Perhaps you want '#{exp.text_value} != 0'?" else type_error "#{exp.type(symtab)} does not support unary #{op} operator" end end else internal_error "Unhandled op #{op}" end end |
#value(symtab) ⇒ Object
Return the compile-time-known value of the node
6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 |
# File 'lib/idlc/ast.rb', line 6254 def value(symtab) val = val_trunc = case op when "-" -exp.value(symtab) when "~" ~exp.value(symtab) when "!" !exp.value(symtab) else internal_error "Unhandled unary op #{op}" end t = type(symtab) if t.integral? if t.width == :unknown value_error("Unknown width for truncation") end val_trunc = truncate(val, t.width, t.signed?) end if op != "~" truncation_warn "#{text_value} is truncated due to insufficient bit width (from #{val} to #{val_trunc})" if val_trunc != val end val_trunc end |