Class: Idl::FunctionType

Inherits:
Type
  • Object
show all
Defined in:
lib/idl/type.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(func_name, func_def_ast, symtab) ⇒ FunctionType

Returns a new instance of FunctionType.



624
625
626
627
628
629
630
# File 'lib/idl/type.rb', line 624

def initialize(func_name, func_def_ast, symtab)
  super(:function, name: func_name)
  @func_def_ast = func_def_ast
  @symtab = symtab

  raise "symtab should be at level 1" unless symtab.levels == 1
end

Instance Attribute Details

#func_def_astObject (readonly)

Returns the value of attribute func_def_ast.



622
623
624
# File 'lib/idl/type.rb', line 622

def func_def_ast
  @func_def_ast
end

Instance Method Details

#apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast) ⇒ Object

apply the arguments as Vars. then add the value to the Var



691
692
693
694
695
696
697
698
699
700
701
702
703
# File 'lib/idl/type.rb', line 691

def apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)
  idx = 0
  @func_def_ast.arguments(symtab).each do |atype, aname|
    func_call_ast.type_error "Missing argument #{idx}" if idx >= argument_nodes.size
    value_result = Idl::AstNode.value_try do
      symtab.add(aname, Var.new(aname, atype, argument_nodes[idx].value(call_site_symtab)))
    end
    Idl::AstNode.value_else(value_result) do
      symtab.add(aname, Var.new(aname, atype))
    end
    idx += 1
  end
end

#apply_template_values(template_values, func_call_ast) ⇒ Object



670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# File 'lib/idl/type.rb', line 670

def apply_template_values(template_values, func_call_ast)
  func_call_ast.type_error "Missing template values" if templated? && template_values.empty?

  func_call_ast.type_error "wrong number of template values in call to #{name}" unless template_names.size == template_values.size

  symtab = @symtab.global_clone

  func_call_ast.type_error "Symbol table should be at global scope" unless symtab.levels == 1

  symtab.push(func_call_ast)

  template_values.each_with_index do |value, idx|
    func_call_ast.type_error "template value should be an Integer (found #{value.class.name})" unless value == :unknown || value.is_a?(Integer)

    symtab.add!(template_names[idx], Var.new(template_names[idx], template_types(symtab)[idx], value, template_index: idx, function_name: @func_def_ast.name))
  end
  symtab
end

#argument_name(index, template_values = [], func_call_ast) ⇒ Object



782
783
784
785
786
787
788
789
790
791
792
793
794
795
# File 'lib/idl/type.rb', line 782

def argument_name(index, template_values = [], func_call_ast)
  return nil if index >= @func_def_ast.num_args

  symtab = apply_template_values(template_values, func_call_ast)
  # apply_arguments(symtab, argument_nodes, call_site_symtab)

  begin
    arguments = @func_def_ast.arguments(symtab)
  ensure
    symtab.pop
    symtab.relase
  end
  arguments[index][1]
end

#argument_type(index, template_values, argument_nodes, call_site_symtab, func_call_ast) ⇒ Object



767
768
769
770
771
772
773
774
775
776
777
778
779
780
# File 'lib/idl/type.rb', line 767

def argument_type(index, template_values, argument_nodes, call_site_symtab, func_call_ast)
  return nil if index >= @func_def_ast.num_args

  symtab = apply_template_values(template_values, func_call_ast)
  # apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)

  begin
    arguments = @func_def_ast.arguments(symtab)
  ensure
    symtab.pop
    symtab.release
  end
  arguments[index][0]
end

#argument_values(symtab, argument_nodes, call_site_symtab, func_call_ast) ⇒ Array<Integer,Boolean>?

Returns:

  • (Array<Integer,Boolean>)

    Array of argument values, if known

  • (nil)

    if at least one argument value is not known



707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
# File 'lib/idl/type.rb', line 707

def argument_values(symtab, argument_nodes, call_site_symtab, func_call_ast)
  idx = 0
  values = []
  @func_def_ast.arguments(symtab).each do |atype, aname|
    func_call_ast.type_error "Missing argument #{idx}" if idx >= argument_nodes.size
    value_result = Idl::AstNode.value_try do
      values << argument_nodes[idx].value(call_site_symtab)
    end
    Idl::AstNode.value_else(value_result) do
      return nil
    end
    idx += 1
  end
  values
end

#bodyObject



797
# File 'lib/idl/type.rb', line 797

def body = @func_def_ast.body

#builtin?Boolean

Returns:

  • (Boolean)


636
# File 'lib/idl/type.rb', line 636

def builtin? = @func_def_ast.builtin?

#cloneObject



632
633
634
# File 'lib/idl/type.rb', line 632

def clone
  FunctionType.new(name, @func_def_ast, @symtab)
end

#num_argsObject



638
# File 'lib/idl/type.rb', line 638

def num_args = @func_def_ast.num_args

#return_type(template_values, func_call_ast) ⇒ Object

return [Type] type of the call return

Parameters:

  • template_values (Array<Integer>)

    Template values for the call, in declaration order

  • func_call_ast (FunctionCallExpressionAst)

    The function call interested in the return type



726
727
728
729
730
731
732
733
734
735
736
737
# File 'lib/idl/type.rb', line 726

def return_type(template_values, func_call_ast)
  symtab = apply_template_values(template_values, func_call_ast)
  # apply_arguments(symtab, argument_nodes, call_site_symtab)

  begin
    type = @func_def_ast.return_type(symtab)
  ensure
    symtab.pop
    symtab.release
  end
  type
end

#return_types(template_values, argument_nodes, call_site_symtab, func_call_ast) ⇒ Array<Type>

Return types

Parameters:

  • template_values (Array<Integer>)

    Template values to apply, required if #templated?

Returns:

  • (Array<Type>)

    return types



754
755
756
757
758
759
760
761
762
763
764
765
# File 'lib/idl/type.rb', line 754

def return_types(template_values, argument_nodes, call_site_symtab, func_call_ast)
  symtab = apply_template_values(template_values, func_call_ast)
  apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)

  begin
    types = @func_def_ast.return_types(symtab)
  ensure
    symtab.pop
    symtab.release
  end
  types
end

#return_value(template_values, argument_nodes, call_site_symtab, func_call_ast) ⇒ Object



739
740
741
742
743
744
745
746
747
748
749
750
# File 'lib/idl/type.rb', line 739

def return_value(template_values, argument_nodes, call_site_symtab, func_call_ast)
  symtab = apply_template_values(template_values, func_call_ast)
  apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)

  begin
    value = @func_def_ast.body.return_value(symtab)
  ensure
    symtab.pop
    symtab.release
  end
  value
end

#template_namesObject



664
# File 'lib/idl/type.rb', line 664

def template_names = @func_def_ast.template_names

#template_types(symtab) ⇒ Object



666
# File 'lib/idl/type.rb', line 666

def template_types(symtab) = @func_def_ast.template_types(symtab)

#templated?Boolean

Returns:

  • (Boolean)


668
# File 'lib/idl/type.rb', line 668

def templated? = @func_def_ast.templated?

#type_check_call(template_values, argument_nodes, call_site_symtab, func_call_ast) ⇒ Object



640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
# File 'lib/idl/type.rb', line 640

def type_check_call(template_values, argument_nodes, call_site_symtab, func_call_ast)
  raise "Missing template values" if templated? && template_values.empty?

  if templated?
    symtab = apply_template_values(template_values, func_call_ast)
    apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)

    @func_def_ast.type_check_template_instance(symtab)

    symtab.pop
    symtab.release
  else
    symtab = @symtab.global_clone

    symtab.push(func_call_ast) # to keep things consistent with template functions, push a scope

    apply_arguments(symtab, argument_nodes, call_site_symtab, func_call_ast)

    @func_def_ast.type_check_from_call(symtab)
    symtab.pop
    symtab.release
  end
end