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.
6207 6208 6209 6210 6211 6212 |
# File 'lib/idlc/ast.rb', line 6207 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
6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 |
# File 'lib/idlc/ast.rb', line 6319 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
6203 |
# File 'lib/idlc/ast.rb', line 6203 def const_eval?(symtab) = expression.const_eval?(symtab) |
#exp ⇒ AstNode
Returns the operated-on expression.
6297 6298 6299 |
# File 'lib/idlc/ast.rb', line 6297 def exp expression end |
#expression ⇒ Object
6205 |
# File 'lib/idlc/ast.rb', line 6205 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
6214 6215 6216 6217 6218 6219 6220 6221 6222 |
# File 'lib/idlc/ast.rb', line 6214 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.
6302 6303 6304 |
# File 'lib/idlc/ast.rb', line 6302 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
6311 6312 6313 6314 6315 6316 |
# File 'lib/idlc/ast.rb', line 6311 def to_h = { "kind" => "unary_operator_expr", "op" => op, "expr" => expression.to_h, "source" => source_yaml } |
#to_idl ⇒ Object
6308 |
# File 'lib/idlc/ast.rb', line 6308 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
6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 |
# File 'lib/idlc/ast.rb', line 6225 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
6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 |
# File 'lib/idlc/ast.rb', line 6241 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
6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 |
# File 'lib/idlc/ast.rb', line 6269 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 |