nitc :: AMethPropdef
nitc :: AMethPropdef :: _auto_super_call
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: _auto_super_inits
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: AMethPropdef :: _foreign_entry_cache
Handle to the entrypoint of this method in the foreign code librarynitc :: AMethPropdef :: _is_autoinit
Is the method annotatedautoinit
?
nitc :: AMethPropdef :: _n_block
The body (in Nit) of the method, if anynitc :: AMethPropdef :: _n_extern_calls
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: _n_extern_code_block
The body (in extern code) of the method, if anynitc :: AMethPropdef :: _n_methid
The name of the method, if anynitc :: AMethPropdef :: _n_signature
The signature of the method, if anynitc :: AMethPropdef :: accept_externmeth
Should we compile the extern methodself
?
nitc :: AMethPropdef :: adapt_block_to_contract
Adapt the block to use the contractsnitc :: AMethPropdef :: auto_super_call
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: auto_super_call=
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: auto_super_inits
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: AMethPropdef :: auto_super_inits=
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: AMethPropdef :: call_commons
Execution of the body of the methodnitc :: AMethPropdef :: call_extern
Call this extern methodnitc :: AMethPropdef :: check_annotation
Verification of the annotation to know if it is a contract annotation.nitc :: AMethPropdef :: check_redef
Verification if the method have an inherited contract to apply it.nitc :: AMethPropdef :: compile_externinit_to_c
Compile an extern factorynitc :: AMethPropdef :: compile_externmeth_to_c
Compile an extern methodnitc :: AMethPropdef :: compile_ffi_method
Compile the necessary wrapper around this extern method or constructornitc :: AMethPropdef :: compile_inside_to_java
Compile the inside of the method bodynitc :: AMethPropdef :: compile_intern_to_java
Compile an intern method using Java primitivesnitc :: AMethPropdef :: defaultinit
nitc :: AMethPropdef :: do_all
Execute all method verification scope flow and typing.nitc :: AMethPropdef :: do_auto_super_init
Collect initializers and build the auto-initnitc :: AMethPropdef :: foreign_callbacks
All foreign callbacks from this methodnitc :: AMethPropdef :: foreign_entry_cache
Handle to the entrypoint of this method in the foreign code librarynitc :: AMethPropdef :: foreign_entry_cache=
Handle to the entrypoint of this method in the foreign code librarynitc :: AMethPropdef :: get_super_candidatedefs
This method returns the list of possible candidates for the current definition.nitc :: AMethPropdef :: insert_artificial_callbacks
Insert additional explicit calls to get the currentJNIEnv
nitc :: AMethPropdef :: intern_call
Interprets a intern or a shortcut extern method.nitc :: AMethPropdef :: is_autoinit=
Is the method annotatedautoinit
?
nitc :: AMethPropdef :: look_like_a_root_init
Can self be used as a root init?nitc :: AMethPropdef :: make
nitc :: AMethPropdef :: n_block=
The body (in Nit) of the method, if anynitc :: AMethPropdef :: n_extern_calls
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: n_extern_calls=
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: n_extern_code_block
The body (in extern code) of the method, if anynitc :: AMethPropdef :: n_extern_code_block=
The body (in extern code) of the method, if anynitc :: AMethPropdef :: n_kwinit=
Theinit
keyword, if any
nitc :: AMethPropdef :: n_methid=
The name of the method, if anynitc :: AMethPropdef :: n_signature
The signature of the method, if anynitc :: AMethPropdef :: n_signature=
The signature of the method, if anynitc :: AMethPropdef :: supported_by_dynamic_ffi
Does this method definition use the FFI and is it supported by the interpreter?nitc :: AMethPropdef :: verify_nitni_callbacks
Verifiy the validity of the explicit callbacks to Nitnitc :: modelize_property $ AMethPropdef :: MPROPDEF
The associated main model entitynitc $ AMethPropdef :: SELF
Type of this instance, automatically specialized in every classnitc :: light_only $ AMethPropdef :: accept_externmeth
Should we compile the extern methodself
?
nitc :: saf_base $ AMethPropdef :: accept_forward_analysis
Apply the forward analysisv
to self
.
nitc :: pretty $ AMethPropdef :: accept_pretty_printer
Start visit ofself
using a PrettyPrinterVisitor
nitc :: nitni_callbacks $ AMethPropdef :: accept_rapid_type_visitor
nitc :: naive_interpreter $ AMethPropdef :: call
Execute ampropdef
associated with the current node.
nitc :: dynamic_loading_ffi $ AMethPropdef :: call_extern
Call this extern methodnitc :: abstract_compiler $ AMethPropdef :: can_inline
nitc :: separate_compiler $ AMethPropdef :: can_inline
The semi-global compilation does not support inlining calls to extern newsnitc :: modelize_property $ AMethPropdef :: check_repeated_types
For parameters, type is always useless in a redef.nitc :: light $ AMethPropdef :: compile_externinit_to_c
Compile an extern factorynitc :: light $ AMethPropdef :: compile_externmeth_to_c
Compile an extern methodnitc :: compiler_ffi $ AMethPropdef :: compile_ffi_support_to_c
nitc :: compiler_serialization $ AMethPropdef :: compile_intern_to_c
nitc :: java_compiler $ AMethPropdef :: compile_to_java
Compile that property definition to java codenitc :: contracts $ AMethPropdef :: create_contracts
Entry point to create a contract (verification of inheritance, or new contract).nitc :: typing $ AMethPropdef :: do_typing
The entry point of the whole typing analysisnitc :: ssa $ AMethPropdef :: generate_basic_blocks
Generate all basic blocks for this codenitc $ AMethPropdef :: hot_location
The location of the important part of the node (identifier or whatever)nitc :: parser_prod $ AMethPropdef :: n_annotations=
All the annotations attached directly to the nodenitc :: parser_prod $ AMethPropdef :: n_block=
The body (in Nit) of the method, if anynitc :: parser_prod $ AMethPropdef :: n_doc=
The documentationnitc :: parser_prod $ AMethPropdef :: n_extern_calls=
The list of declared callbacks (for extern methods)nitc :: parser_prod $ AMethPropdef :: n_extern_code_block=
The body (in extern code) of the method, if anynitc :: parser_prod $ AMethPropdef :: n_kwdo=
Thedo
keyword
nitc :: parser_prod $ AMethPropdef :: n_kwend=
Theend
keyword
nitc :: parser_prod $ AMethPropdef :: n_kwinit=
Theinit
keyword, if any
nitc :: parser_prod $ AMethPropdef :: n_kwisa=
Theisa
keyword, if any
nitc :: parser_prod $ AMethPropdef :: n_kwmeth=
Thefun
keyword, if any
nitc :: parser_prod $ AMethPropdef :: n_kwnew=
Thenew
keyword, if any
nitc :: parser_prod $ AMethPropdef :: n_kwredef=
Theredef
keyword
nitc :: parser_prod $ AMethPropdef :: n_methid=
The name of the method, if anynitc :: parser_prod $ AMethPropdef :: n_signature=
The signature of the method, if anynitc :: parser_prod $ AMethPropdef :: n_visibility=
The declared visibilitynitc :: variables_numbering $ AMethPropdef :: numbering_variables
Assign a position in the environment to each local variablenitc :: parser_prod $ AMethPropdef :: replace_child
Replace a child with an other node in the ASTnitc :: java $ AMethPropdef :: verify_nitni_callbacks
Verifiy the validity of the explicit callbacks to Nitnitc :: parser_prod $ AMethPropdef :: visit_all
Visit all nodes in order.nitc :: APropdef :: _after_flow_context
The ending flownitc :: AMethPropdef :: _auto_super_call
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: _auto_super_inits
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: APropdef :: _basic_block
The first basic block of the codenitc :: APropdef :: _before_flow_context
The starting flownitc :: APropdef :: _environment_size
The size of the environment to create to call this methodnitc :: Prod :: _first_location
Location on the first token after the start of a productionnitc :: Prod :: _first_token
The first token of the production in the ASTnitc :: AMethPropdef :: _foreign_entry_cache
Handle to the entrypoint of this method in the foreign code librarynitc :: AMethPropdef :: _is_autoinit
Is the method annotatedautoinit
?
nitc :: ANode :: _is_broken
The indication that the node did not pass some semantic verifications.nitc :: APropdef :: _is_compiled
Indicite if this propdef was compilenitc :: APropdef :: _is_generated
If true, the basic blocks where generatednitc :: APropdef :: _is_numbering
Indicate if the variables numbering has been donenitc :: APropdef :: _is_phased
Is the propdef already analyzed byrun_phases_on_npropdef
.
nitc :: Prod :: _last_token
The last token of the production in the ASTnitc :: Prod :: _n_annotations
All the annotations attached directly to the nodenitc :: AMethPropdef :: _n_block
The body (in Nit) of the method, if anynitc :: AMethPropdef :: _n_extern_calls
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: _n_extern_code_block
The body (in extern code) of the method, if anynitc :: AMethPropdef :: _n_methid
The name of the method, if anynitc :: AMethPropdef :: _n_signature
The signature of the method, if anynitc :: ADefinition :: _n_visibility
The declared visibilitynitc :: APropdef :: _object_sites
Contain all AST-parts related to object mechanisms the propdef has:nitc :: APropdef :: _return_mark
The break escape mark associated with the returnnitc :: APropdef :: _selfvariable
The variable associated to the receiver (if any)nitc :: APropdef :: _variables
The variables contained in the body on this propdefnitc :: ANode :: accept_ast_validation
nitc :: ANode :: accept_auto_super_init
nitc :: AMethPropdef :: accept_externmeth
Should we compile the extern methodself
?
nitc :: ANode :: accept_flow_visitor
nitc :: ANode :: accept_forward_analysis
Apply the forward analysisv
to self
.
nitc :: ANode :: accept_literal
nitc :: ANode :: accept_post_typing
nitc :: ANode :: accept_pretty_printer
Start visit ofself
using a PrettyPrinterVisitor
nitc :: ANode :: accept_reaching_defs
Apply a ReachingDefsAnalysis toself
.
nitc :: ANode :: accept_regex_visitor
nitc :: ANode :: accept_scope_visitor
nitc :: ANode :: accept_simple_misc
nitc :: ANode :: accept_string_finder
nitc :: AMethPropdef :: adapt_block_to_contract
Adapt the block to use the contractsnitc :: APropdef :: after_flow_context=
The ending flownitc :: ANode :: after_simple_misc
nitc :: AMethPropdef :: auto_super_call
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: auto_super_call=
In case of redefined constructors, is an implicit call-to-super required?nitc :: AMethPropdef :: auto_super_inits
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: AMethPropdef :: auto_super_inits=
In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)nitc :: ANode :: bad_expr_message
An additional information message to explain the role of a child expression.nitc :: APropdef :: basic_block
The first basic block of the codenitc :: APropdef :: basic_block=
The first basic block of the codenitc :: APropdef :: before_flow_context
The starting flownitc :: APropdef :: before_flow_context=
The starting flownitc :: APropdef :: build_property
nitc :: APropdef :: build_signature
mpropdef
associated with the current node.
nitc :: AMethPropdef :: call_commons
Execution of the body of the methodnitc :: AMethPropdef :: call_extern
Call this extern methodnitc :: APropdef :: can_inline
nitc :: AMethPropdef :: check_annotation
Verification of the annotation to know if it is a contract annotation.nitc :: ANode :: check_callsite
nitc :: AMethPropdef :: check_redef
Verification if the method have an inherited contract to apply it.nitc :: APropdef :: check_redef_keyword
nitc :: APropdef :: check_repeated_types
Checks for useless type in redef signatures.nitc :: APropdef :: check_signature
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
nitc :: ANode :: collect_annotations_by_name
Do a deep search and return an array of node that are annotatednitc :: Prod :: collect_comments
Collect allTComment
contained in the production
nitc :: ANode :: collect_length
Collect the length (inChar
) of the node.
nitc :: ANode :: collect_tokens_by_text
Do a deep search and return an array of tokens that match a given textnitc :: ANode :: common_parent
The most specific common parent betweenself
and other
nitc :: AMethPropdef :: compile_externinit_to_c
Compile an extern factorynitc :: AMethPropdef :: compile_externmeth_to_c
Compile an extern methodnitc :: AMethPropdef :: compile_ffi_method
Compile the necessary wrapper around this extern method or constructornitc :: AMethPropdef :: compile_inside_to_java
Compile the inside of the method bodynitc :: AMethPropdef :: compile_intern_to_java
Compile an intern method using Java primitivesnitc :: APropdef :: compile_to_c
nitc :: APropdef :: compile_to_java
Compile that property definition to java codenitc :: APropdef :: compute_phi
Compute the first phase of SSA algorithm: placing phi-functionsnitc :: ANode :: create_contracts
nitc :: ANode :: decorate_tag
Add aditionnal information on a child-token and return an additionnal HInfoBox on itcore :: Object :: defaultinit
nitc :: ANode :: defaultinit
nitc :: ADefinition :: defaultinit
nitc :: Prod :: defaultinit
nitc :: AMethPropdef :: defaultinit
nitc :: TablesCapable :: defaultinit
nitc :: APropdef :: defaultinit
core :: Cloneable :: defaultinit
nitc :: AMethPropdef :: do_all
Execute all method verification scope flow and typing.nitc :: AMethPropdef :: do_auto_super_init
Collect initializers and build the auto-initnitc :: ANode :: do_cloneable
nitc :: APropdef :: do_local_var_init
Entry point of the whole local variable initialization verifiernitc :: APropdef :: environment_size
The size of the environment to create to call this methodnitc :: APropdef :: environment_size=
The size of the environment to create to call this methodnitc :: Prod :: first_location
Location on the first token after the start of a productionnitc :: Prod :: first_location=
Location on the first token after the start of a productionnitc :: Prod :: first_token
The first token of the production in the ASTnitc :: Prod :: first_token=
The first token of the production in the ASTnitc :: ANode :: force_block=
Forceself
to be rendered as a block.
nitc :: ANode :: force_inline=
Forceself
to be rendered as a line.
nitc :: AMethPropdef :: foreign_callbacks
All foreign callbacks from this methodnitc :: AMethPropdef :: foreign_entry_cache
Handle to the entrypoint of this method in the foreign code librarynitc :: AMethPropdef :: foreign_entry_cache=
Handle to the entrypoint of this method in the foreign code librarynitc :: ANode :: full_transform_visitor
nitc :: APropdef :: generate_basic_blocks
Generate all basic blocks for this codenitc :: Prod :: get_annotations
Return all its annotations of a given name in the order of their declarationnitc :: Prod :: get_single_annotation
Try to get its single annotation with a given namenitc :: AMethPropdef :: get_super_candidatedefs
This method returns the list of possible candidates for the current definition.nitc :: ANode :: hot_location
The location of the important part of the node (identifier or whatever)nitc :: AMethPropdef :: insert_artificial_callbacks
Insert additional explicit calls to get the currentJNIEnv
nitc :: AMethPropdef :: intern_call
Interprets a intern or a shortcut extern method.nitc :: AMethPropdef :: is_autoinit=
Is the method annotatedautoinit
?
nitc :: ANode :: is_broken=
The indication that the node did not pass some semantic verifications.nitc :: APropdef :: is_compiled=
Indicite if this propdef was compilenitc :: APropdef :: is_generated=
If true, the basic blocks where generatednitc :: ANode :: is_noserialize
Is this node annotated to not be made serializable?nitc :: APropdef :: is_numbering
Indicate if the variables numbering has been donenitc :: APropdef :: is_numbering=
Indicate if the variables numbering has been donenitc :: APropdef :: is_phased=
Is the propdef already analyzed byrun_phases_on_npropdef
.
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
nitc :: ANode :: is_serialize
Is this node annotated to be made serializable?nitc :: ANode :: is_structural
Isself
a token or a pure-structural production like AQId
?
nitc :: Prod :: last_token
The last token of the production in the ASTnitc :: Prod :: last_token=
The last token of the production in the ASTnitc :: TablesCapable :: lexer_accept
The accept value of the lexer at initc :: TablesCapable :: lexer_goto
The goto value of the lexer at row i, column j-1nitc :: AMethPropdef :: look_like_a_root_init
Can self be used as a root init?nitc :: AMethPropdef :: make
nitc :: ANode :: must_be_block
Doesself
have to be rendered as a block?
nitc :: ANode :: must_be_inline
Doesself
have be rendered as a line?
nitc :: Prod :: n_annotations
All the annotations attached directly to the nodenitc :: Prod :: n_annotations=
All the annotations attached directly to the nodenitc :: AMethPropdef :: n_block=
The body (in Nit) of the method, if anynitc :: AMethPropdef :: n_extern_calls
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: n_extern_calls=
The list of declared callbacks (for extern methods)nitc :: AMethPropdef :: n_extern_code_block
The body (in extern code) of the method, if anynitc :: AMethPropdef :: n_extern_code_block=
The body (in extern code) of the method, if anynitc :: AMethPropdef :: n_kwinit=
Theinit
keyword, if any
nitc :: AMethPropdef :: n_methid=
The name of the method, if anynitc :: AMethPropdef :: n_signature
The signature of the method, if anynitc :: AMethPropdef :: n_signature=
The signature of the method, if anynitc :: ADefinition :: n_visibility=
The declared visibilitycore :: Object :: native_class_name
The class name of the object in CString format.nitc :: APropdef :: numbering_variables
Numbering the variable inside the propdefnitc :: APropdef :: object_sites
Contain all AST-parts related to object mechanisms the propdef has:nitc :: APropdef :: object_sites=
Contain all AST-parts related to object mechanisms the propdef has:core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: ANode :: parentize_tokens
Visit the AST and computes advanced AST attributes on Tokens and Prodnitc :: TablesCapable :: parser_action
The action value of the parser at row i, column j-1nitc :: TablesCapable :: parser_goto
The goto value of the parser at row i, column j-1nitc :: APropdef :: propagate_dependences
Propagate the dependences of the phi-functions into following variablesnitc :: APropdef :: rename_variables
Compute the second phase of SSA algorithm: renaming variablesnitc :: ANode :: replace_child
Replace a child with an other node in the ASTnitc :: ANode :: replace_with
Replace itself with an other node in the ASTnitc :: APropdef :: return_mark
The break escape mark associated with the returnnitc :: APropdef :: return_mark=
The break escape mark associated with the returnnitc :: APropdef :: returnvar=
The return variable of the propdefnitc :: APropdef :: selfvariable
The variable associated to the receiver (if any)nitc :: APropdef :: selfvariable=
The variable associated to the receiver (if any)nitc :: APropdef :: ssa_destruction
Transform SSA-representation into an executable code (delete phi-functions)nitc :: Prod :: start_token
The token where the production really start (skipping ADoc).nitc :: AMethPropdef :: supported_by_dynamic_ffi
Does this method definition use the FFI and is it supported by the interpreter?nitc :: APropdef :: variables=
The variables contained in the body on this propdefnitc :: AMethPropdef :: verify_nitni_callbacks
Verifiy the validity of the explicit callbacks to Nitnitc :: APropdef :: visit_annotations
Factorize annotations visit for all APropdef.nitc :: APropdef :: visit_block
Factorize block visit for APropdefs.nitc :: ANode :: was_inline
Doesself
was written in one line before transformation?
# A definition of all kind of method (including constructors)
class AMethPropdef
super APropdef
# The `fun` keyword, if any
var n_kwmeth: nullable TKwmeth = null is writable
# The `init` keyword, if any
var n_kwinit: nullable TKwinit = null is writable
# The `isa` keyword, if any
var n_kwisa: nullable TKwisa = null is writable
# The `new` keyword, if any
var n_kwnew: nullable TKwnew = null is writable
# The name of the method, if any
var n_methid: nullable AMethid = null is writable
# The signature of the method, if any
var n_signature: nullable ASignature = null is writable
# The `do` keyword
var n_kwdo: nullable TKwdo = null is writable
# The body (in Nit) of the method, if any
var n_block: nullable AExpr = null is writable
# The `end` keyword
var n_kwend: nullable TKwend = null is writable
# The list of declared callbacks (for extern methods)
var n_extern_calls: nullable AExternCalls = null is writable
# The body (in extern code) of the method, if any
var n_extern_code_block: nullable AExternCodeBlock = null is writable
redef fun hot_location
do
if n_methid != null then
return n_methid.location
else if n_kwinit != null then
return n_kwinit.location
else if n_kwnew != null then
return n_kwnew.location
else
return location
end
end
end
src/parser/parser_nodes.nit:1404,1--1453,3
redef class AMethPropdef
init init_amethpropdef (
n_doc: nullable ADoc,
n_kwredef: nullable TKwredef,
n_visibility: nullable AVisibility,
n_kwmeth: nullable TKwmeth,
n_kwinit: nullable TKwinit,
n_kwisa: nullable TKwisa,
n_kwnew: nullable TKwnew,
n_methid: nullable AMethid,
n_signature: nullable ASignature,
n_annotations: nullable AAnnotations,
n_extern_calls: nullable AExternCalls,
n_extern_code_block: nullable AExternCodeBlock,
n_kwdo: nullable TKwdo,
n_block: nullable AExpr,
n_kwend: nullable TKwend
)
do
_n_doc = n_doc
if n_doc != null then n_doc.parent = self
_n_kwredef = n_kwredef
if n_kwredef != null then n_kwredef.parent = self
_n_visibility = n_visibility.as(not null)
n_visibility.parent = self
_n_kwmeth = n_kwmeth
if n_kwmeth != null then n_kwmeth.parent = self
_n_kwinit = n_kwinit
if n_kwinit != null then n_kwinit.parent = self
_n_kwisa = n_kwisa
if n_kwisa != null then n_kwisa.parent = self
_n_kwnew = n_kwnew
if n_kwnew != null then n_kwnew.parent = self
_n_methid = n_methid
if n_methid != null then n_methid.parent = self
_n_signature = n_signature.as(not null)
n_signature.parent = self
_n_annotations = n_annotations
if n_annotations != null then n_annotations.parent = self
_n_extern_calls = n_extern_calls
if n_extern_calls != null then n_extern_calls.parent = self
_n_extern_code_block = n_extern_code_block
if n_extern_code_block != null then n_extern_code_block.parent = self
_n_kwdo = n_kwdo
if n_kwdo != null then n_kwdo.parent = self
_n_block = n_block
if n_block != null then n_block.parent = self
_n_kwend = n_kwend
if n_kwend != null then n_kwend.parent = self
end
redef fun replace_child(old_child: ANode, new_child: nullable ANode)
do
if _n_doc == old_child then
n_doc = new_child.as(nullable ADoc)
return
end
if _n_kwredef == old_child then
n_kwredef = new_child.as(nullable TKwredef)
return
end
if _n_visibility == old_child then
n_visibility = new_child.as(AVisibility)
return
end
if _n_kwmeth == old_child then
n_kwmeth = new_child.as(nullable TKwmeth)
return
end
if _n_kwinit == old_child then
n_kwinit = new_child.as(nullable TKwinit)
return
end
if _n_kwisa == old_child then
n_kwisa = new_child.as(nullable TKwisa)
return
end
if _n_kwnew == old_child then
n_kwnew = new_child.as(nullable TKwnew)
return
end
if _n_methid == old_child then
n_methid = new_child.as(nullable AMethid)
return
end
if _n_signature == old_child then
n_signature = new_child.as(ASignature)
return
end
if _n_annotations == old_child then
n_annotations = new_child.as(nullable AAnnotations)
return
end
if _n_extern_calls == old_child then
n_extern_calls = new_child.as(nullable AExternCalls)
return
end
if _n_extern_code_block == old_child then
n_extern_code_block = new_child.as(nullable AExternCodeBlock)
return
end
if _n_kwdo == old_child then
n_kwdo = new_child.as(nullable TKwdo)
return
end
if _n_block == old_child then
n_block = new_child.as(nullable AExpr)
return
end
if _n_kwend == old_child then
n_kwend = new_child.as(nullable TKwend)
return
end
end
redef fun n_doc=(node)
do
_n_doc = node
if node != null then node.parent = self
end
redef fun n_kwredef=(node)
do
_n_kwredef = node
if node != null then node.parent = self
end
redef fun n_visibility=(node)
do
_n_visibility = node
node.parent = self
end
redef fun n_kwmeth=(node)
do
_n_kwmeth = node
if node != null then node.parent = self
end
redef fun n_kwinit=(node)
do
_n_kwinit = node
if node != null then node.parent = self
end
redef fun n_kwisa=(node)
do
_n_kwisa = node
if node != null then node.parent = self
end
redef fun n_kwnew=(node)
do
_n_kwnew = node
if node != null then node.parent = self
end
redef fun n_methid=(node)
do
_n_methid = node
if node != null then node.parent = self
end
redef fun n_signature=(node)
do
_n_signature = node
node.parent = self
end
redef fun n_annotations=(node)
do
_n_annotations = node
if node != null then node.parent = self
end
redef fun n_extern_calls=(node)
do
_n_extern_calls = node
if node != null then node.parent = self
end
redef fun n_extern_code_block=(node)
do
_n_extern_code_block = node
if node != null then node.parent = self
end
redef fun n_kwdo=(node)
do
_n_kwdo = node
if node != null then node.parent = self
end
redef fun n_block=(node)
do
_n_block = node
if node != null then node.parent = self
end
redef fun n_kwend=(node)
do
_n_kwend = node
if node != null then node.parent = self
end
redef fun visit_all(v: Visitor)
do
v.enter_visit(_n_doc)
v.enter_visit(_n_kwredef)
v.enter_visit(_n_visibility)
v.enter_visit(_n_kwmeth)
v.enter_visit(_n_kwinit)
v.enter_visit(_n_kwisa)
v.enter_visit(_n_kwnew)
v.enter_visit(_n_methid)
v.enter_visit(_n_signature)
v.enter_visit(_n_annotations)
v.enter_visit(_n_extern_calls)
v.enter_visit(_n_extern_code_block)
v.enter_visit(_n_kwdo)
v.enter_visit(_n_block)
v.enter_visit(_n_kwend)
end
end
src/parser/parser_prod.nit:1140,1--1350,3
redef class AMethPropdef
redef fun accept_forward_analysis(v) do
v.current_inset = v.new_initial_method_flow(self)
v.current_outset = v.current_inset.clone
v.insets[self] = v.current_inset
visit_all(v)
v.outsets[self] = v.current_outset
end
end
src/saf/saf_base.nit:238,1--246,3
redef class AMethPropdef
redef type MPROPDEF: MMethodDef
# Is the method annotated `autoinit`?
var is_autoinit = false
# Can self be used as a root init?
private fun look_like_a_root_init(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
do
# Need the `init` keyword
if n_kwinit == null then return false
# Need to by anonymous
if self.n_methid != null then return false
# No annotation on itself
if get_single_annotation("old_style_init", modelbuilder) != null then return false
# Nor on its module
var amod = self.parent.parent.as(AModule)
var amoddecl = amod.n_moduledecl
if amoddecl != null then
var old = amoddecl.get_single_annotation("old_style_init", modelbuilder)
if old != null then return false
end
# No parameters
if self.n_signature.n_params.length > 0 then
modelbuilder.advice(self, "old-init", "Warning: init with signature in {mclassdef}")
return false
end
# Cannot be private or something
if not self.n_visibility isa APublicVisibility then
modelbuilder.advice(self, "old-init", "Warning: non-public init in {mclassdef}")
return false
end
return true
end
redef fun build_property(modelbuilder, mclassdef)
do
var n_kwinit = n_kwinit
var n_kwnew = n_kwnew
var is_new = n_kwnew != null
var is_init = n_kwinit != null or is_new
var name: String
var amethodid = self.n_methid
var name_node: ANode
var is_old_style_init = false
if amethodid == null then
if n_kwinit != null then
name = "init"
name_node = n_kwinit
var old_style_annot = get_single_annotation("old_style_init", modelbuilder)
if old_style_annot != null or self.n_signature.n_params.not_empty then
name = "defaultinit"
if old_style_annot != null then is_old_style_init = true
end
else if n_kwnew != null then
name = "new"
name_node = n_kwnew
else
name = "main"
name_node = self
end
else if amethodid isa AIdMethid then
name = amethodid.n_id.text
name_node = amethodid
else
# operator, bracket or assign
name = amethodid.collect_text
name_node = amethodid
var arity = self.n_signature.n_params.length
if name == "+" and arity == 0 then
name = "unary +"
else if name == "-" and arity == 0 then
name = "unary -"
else if name == "~" and arity == 0 then
name = "unary ~"
else
if amethodid.is_binary and arity != 1 then
modelbuilder.error(self.n_signature, "Syntax Error: binary operator `{name}` requires exactly one parameter; got {arity}.")
else if amethodid.min_arity > arity then
modelbuilder.error(self.n_signature, "Syntax Error: `{name}` requires at least {amethodid.min_arity} parameter(s); got {arity}.")
end
end
end
var look_like_a_root_init = look_like_a_root_init(modelbuilder, mclassdef)
var mprop: nullable MMethod = null
if not is_init or n_kwredef != null or look_like_a_root_init then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
if mprop == null and look_like_a_root_init then
mprop = modelbuilder.the_root_init_mmethod
var nb = n_block
if nb isa ABlockExpr and nb.n_expr.is_empty and n_doc == null then
modelbuilder.advice(self, "useless-init", "Warning: useless empty init in {mclassdef}")
end
end
if mprop == null then
var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
mprop = new MMethod(mclassdef, name, self.location, mvisibility)
if look_like_a_root_init and modelbuilder.the_root_init_mmethod == null then
modelbuilder.the_root_init_mmethod = mprop
mprop.is_root_init = true
end
mprop.is_init = is_init
mprop.is_new = is_new
if is_new then mclassdef.mclass.has_new_factory = true
if name == "sys" then mprop.is_toplevel = true # special case for sys allowed in `new` factories
if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then
mprop.is_broken = true
return
end
else
if mprop.is_broken then return
if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
end
# Check name conflicts in the local class for constructors.
if is_init then
for p, n in mclassdef.mprop2npropdef do
if p != mprop and p isa MMethod and p.name == name then
if not check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, p) then
mprop.is_broken = true
return
end
break
end
end
end
mclassdef.mprop2npropdef[mprop] = self
var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
if mpropdef.name == "defaultinit" and mclassdef.is_intro then
assert mclassdef.default_init == null
mpropdef.is_old_style_init = is_old_style_init
mclassdef.default_init = mpropdef
# Set the initializers with the mproperty.
# This point is need when a super class define this own default_init and inherited class use the default_init generated automaticlely.
mpropdef.initializers.add mprop
mpropdef.is_calling_init = true
end
set_doc(mpropdef, modelbuilder)
self.mpropdef = mpropdef
modelbuilder.mpropdef2npropdef[mpropdef] = self
if mpropdef.is_intro then
modelbuilder.toolcontext.info("{mpropdef} introduces new method {mprop.full_name}", 4)
else
modelbuilder.toolcontext.info("{mpropdef} redefines method {mprop.full_name}", 4)
end
end
redef fun build_signature(modelbuilder)
do
var mpropdef = self.mpropdef
if mpropdef == null then return # Error thus skiped
var mproperty = mpropdef.mproperty
var mclassdef = mpropdef.mclassdef
var mmodule = mclassdef.mmodule
var nsig = self.n_signature
var accept_special_last_parameter = self.n_methid == null or self.n_methid.accept_special_last_parameter
var return_is_mandatory = self.n_methid != null and self.n_methid.return_is_mandatory
# Retrieve info from the signature AST
var param_names = new Array[String] # Names of parameters from the AST
var param_types = new Array[MType] # Types of parameters from the AST
var vararg_rank = -1
var ret_type: nullable MType = null # Return type from the AST
if nsig != null then
if not nsig.visit_signature(modelbuilder, mclassdef) then return
param_names = nsig.param_names
param_types = nsig.param_types
vararg_rank = nsig.vararg_rank
ret_type = nsig.ret_type
end
# Look for some signature to inherit
# FIXME: do not inherit from the intro, but from the most specific
var msignature: nullable MSignature = null
if not mpropdef.is_intro then
msignature = mproperty.intro.msignature
if msignature == null then return # Skip error
# The local signature is adapted to use the local formal types, if any.
msignature = msignature.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mmodule, false)
# Check inherited signature arity
if param_names.length != msignature.arity then
var node: ANode
if nsig != null then node = nsig else node = self
modelbuilder.error(node, "Redef Error: expected {msignature.arity} parameter(s) for `{mproperty.name}{msignature}`; got {param_names.length}. See introduction at `{mproperty.full_name}`.")
return
end
else if mproperty.is_init and not mproperty.is_new then
# FIXME UGLY: inherit signature from a super-constructor
for msupertype in mclassdef.supertypes do
msupertype = msupertype.anchor_to(mmodule, mclassdef.bound_mtype)
var candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, mproperty.name)
if candidate != null then
if msignature == null then
msignature = candidate.intro.as(MMethodDef).msignature
end
end
end
end
# Inherit the signature
if msignature != null and param_names.length != param_types.length and param_names.length == msignature.arity and param_types.length == 0 then
# Parameters are untyped, thus inherit them
param_types = new Array[MType]
for mparameter in msignature.mparameters do
param_types.add(mparameter.mtype)
end
vararg_rank = msignature.vararg_rank
end
if msignature != null and ret_type == null then
ret_type = msignature.return_mtype
end
if param_names.length != param_types.length then
# Some parameters are typed, other parameters are not typed.
modelbuilder.error(nsig.n_params[param_types.length], "Error: untyped parameter `{param_names[param_types.length]}'.")
return
end
var mparameters = new Array[MParameter]
for i in [0..param_names.length[ do
var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
if nsig != null then nsig.n_params[i].mparameter = mparameter
mparameters.add(mparameter)
end
# In `new`-factories, the return type is by default the classtype.
if ret_type == null and mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
# Special checks for operator methods
if not accept_special_last_parameter and mparameters.not_empty and mparameters.last.is_vararg then
modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mproperty.name}`.")
end
if ret_type == null and return_is_mandatory then
modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mproperty.name}`.")
end
msignature = new MSignature(mparameters, ret_type)
mpropdef.msignature = msignature
mpropdef.is_abstract = self.get_single_annotation("abstract", modelbuilder) != null
mpropdef.is_intern = self.get_single_annotation("intern", modelbuilder) != null
mpropdef.is_extern = self.n_extern_code_block != null or self.get_single_annotation("extern", modelbuilder) != null
# Check annotations
var at = self.get_single_annotation("lazy", modelbuilder)
if at != null then modelbuilder.error(at, "Syntax Error: `lazy` must be used on attributes.")
var atautoinit = self.get_single_annotation("autoinit", modelbuilder)
if atautoinit != null then
if not mpropdef.is_intro then
modelbuilder.error(atautoinit, "Error: `autoinit` cannot be set on redefinitions.")
else if not mclassdef.is_intro then
modelbuilder.error(atautoinit, "Error: `autoinit` cannot be used in class refinements.")
else
self.is_autoinit = true
end
end
end
redef fun check_signature(modelbuilder)
do
var mpropdef = self.mpropdef
if mpropdef == null then return # Error thus skiped
var mclassdef = mpropdef.mclassdef
var mmodule = mclassdef.mmodule
var nsig = self.n_signature
var mysignature = mpropdef.msignature
if mysignature == null then return # Error thus skiped
# Check
if nsig != null then
if not nsig.check_signature(modelbuilder, mclassdef) then
mpropdef.msignature = null # invalidate
mpropdef.is_broken = true
return # Forward error
end
end
# Lookup for signature in the precursor
# FIXME all precursors should be considered
if not mpropdef.is_intro then
var msignature = mpropdef.mproperty.intro.msignature
if msignature == null then return
var precursor_ret_type = msignature.return_mtype
var ret_type = mysignature.return_mtype
if ret_type != null and precursor_ret_type == null then
modelbuilder.error(nsig.n_type, "Redef Error: `{mpropdef.mproperty}` is a procedure, not a function.")
mpropdef.msignature = null
mpropdef.is_broken = true
return
end
if mysignature.arity > 0 then
# Check parameters types
for i in [0..mysignature.arity[ do
var myt = mysignature.mparameters[i].mtype
var prt = msignature.mparameters[i].mtype
var node = nsig.n_params[i]
if not modelbuilder.check_sametype(node, mmodule, mclassdef.bound_mtype, myt, prt) then
modelbuilder.error(node, "Redef Error: expected `{prt}` for parameter `{mysignature.mparameters[i].name}'; got `{myt}`.")
mpropdef.msignature = null
mpropdef.is_broken = true
end
end
end
if precursor_ret_type != null then
var node: nullable ANode = null
if nsig != null then node = nsig.n_type
if node == null then node = self
if ret_type == null then
# Inherit the return type
ret_type = precursor_ret_type
else if not modelbuilder.check_subtype(node, mmodule, mclassdef.bound_mtype, ret_type, precursor_ret_type) then
modelbuilder.error(node, "Redef Error: expected `{precursor_ret_type}` for return type; got `{ret_type}`.")
mpropdef.msignature = null
mpropdef.is_broken = true
end
end
end
if nsig != null then
# Check parameters visibility
for i in [0..mysignature.arity[ do
var nt = nsig.n_params[i].n_type
if nt != null then modelbuilder.check_visibility(nt, nt.mtype.as(not null), mpropdef)
end
var nt = nsig.n_type
if nt != null then modelbuilder.check_visibility(nt, nt.mtype.as(not null), mpropdef)
end
check_repeated_types(modelbuilder)
end
# For parameters, type is always useless in a redef.
# For return type, type is useless if not covariant with introduction.
redef fun check_repeated_types(modelbuilder) do
var mpropdef = self.mpropdef
if mpropdef == null then return
if mpropdef.is_intro or n_signature == null then return
# check params
for param in n_signature.n_params do
if param.n_type != null then
modelbuilder.advice(param.n_type, "useless-signature", "Warning: useless type repetition on parameter `{param.n_id.text}` for redefined method `{mpropdef.name}`")
end
end
# get intro
var intro = mpropdef.mproperty.intro
var n_intro = modelbuilder.mpropdef2npropdef.get_or_null(intro)
if n_intro == null or not n_intro isa AMethPropdef then return
# check return type
var ret_type = n_signature.ret_type
if ret_type != null and ret_type == n_intro.n_signature.ret_type then
modelbuilder.advice(n_signature.n_type, "useless-signature", "Warning: useless return type repetition for redefined method `{mpropdef.name}`")
end
end
end
src/modelize/modelize_property.nit:758,1--1123,3
redef class AMethPropdef
# Compile the necessary wrapper around this extern method or constructor
fun compile_ffi_method(mmodule: MModule)
do
assert n_extern_code_block != null
if mmodule.compiled_ffi_methods.has(self) then return
mmodule.compiled_ffi_methods.add self
var language = n_extern_code_block.language
assert language != null
mmodule.present_languages.add(language)
n_extern_code_block.language.compile_extern_method(
n_extern_code_block.as(not null), self, mmodule.ffi_ccu.as(not null), mmodule)
end
end
src/ffi/light_ffi.nit:116,1--131,3
redef class AMethPropdef
redef fun accept_pretty_printer(v) do
# TODO: Handle extern annotations
var before = v.indent
super
if n_kwinit != null then v.visit n_kwinit
if n_kwmeth != null then v.visit n_kwmeth
if n_kwnew != null then v.visit n_kwnew
if not n_methid == null then
v.adds
v.visit n_methid
end
v.visit n_signature
var annot_inline = visit_annotations(v, n_annotations)
if n_extern_calls != null or n_extern_code_block != null then
v.adds
if n_extern_calls != null then v.visit n_extern_calls
if n_extern_code_block != null then v.visit n_extern_code_block
end
visit_block(v, n_block, annot_inline)
v.addn
assert v.indent == before
end
# Can be inlined if:
# * block is empty or can be inlined
# * contains no comments
redef fun is_inlinable do
if not super then return false
if n_annotations != null and not n_annotations.is_inlinable then return false
if n_block != null and not n_block.is_inlinable then return false
if n_extern_calls != null and not n_extern_calls.is_inlinable then return false
if n_extern_code_block != null and not n_extern_code_block.is_inlinable then return false
if not collect_comments.is_empty then return false
return true
end
end
src/pretty.nit:960,1--1002,3
redef class AMethPropdef
redef fun do_typing(modelbuilder: ModelBuilder)
do
var mpropdef = self.mpropdef
if mpropdef == null then return # skip error
var v = new TypeVisitor(modelbuilder, mpropdef)
self.selfvariable = v.selfvariable
var mmethoddef = self.mpropdef.as(not null)
var msignature = mmethoddef.msignature
if msignature == null then return # skip error
for i in [0..msignature.arity[ do
var mtype = msignature.mparameters[i].mtype
if msignature.vararg_rank == i then
var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
if arrayclass == null then return # Skip error
mtype = arrayclass.get_mtype([mtype])
end
var variable = self.n_signature.n_params[i].variable
assert variable != null
variable.declared_type = mtype
end
var nblock = self.n_block
if nblock == null then return
loop
v.dirty = false
v.visit_stmt(nblock)
if not v.has_loop or not v.dirty then break
end
var post_visitor = new PostTypingVisitor(v)
post_visitor.enter_visit(self)
if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
# We reach the end of the function without having a return, it is bad
v.error(self, "Error: reached end of function; expected `return` with a value.")
end
end
end
src/semantize/typing.nit:896,1--937,3
redef class AMethPropdef
# In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)
var auto_super_inits: nullable Array[CallSite] = null
# In case of redefined constructors, is an implicit call-to-super required?
var auto_super_call = false
# Collect initializers and build the auto-init
fun do_auto_super_init(modelbuilder: ModelBuilder)
do
var mclassdef = self.parent.as(AClassdef).mclassdef
if mclassdef == null or mclassdef.is_broken then return # skip error
var mpropdef = self.mpropdef
if mpropdef == null or mpropdef.is_broken then return # skip error
var mmodule = mpropdef.mclassdef.mmodule
var anchor = mclassdef.bound_mtype
var recvtype = mclassdef.mclass.mclass_type
# Get the annotation, but check its pertinence before returning
var nosuper = get_single_annotation("nosuper", modelbuilder)
# Collect only for constructors
if not mpropdef.mproperty.is_init or mpropdef.mproperty.is_new then
if nosuper != null then modelbuilder.error(nosuper, "Error: `nosuper` only allowed in `init`.")
return
end
# Now we search for the absence of any explicit super-init invocation
# * via a "super"
# * via a call of an other init
var nblock = self.n_block
if nblock != null then
var v = new AutoSuperInitVisitor
v.enter_visit(nblock)
var anode = v.has_explicit_super_init
if anode != null then
if nosuper != null then modelbuilder.error(anode, "Error: method is annotated `nosuper` but a super-constructor call is present.")
return
end
if v.is_broken then return # skip
end
if nosuper != null then return
# Still here? So it means that we must add an implicit super-call on redefinitions.
if not mpropdef.is_intro then
auto_super_call = true
mpropdef.has_supercall = true
modelbuilder.toolcontext.info("Auto-super call for {mpropdef}", 4)
return
end
# Still here? So it means that we must determine what super inits need to be automatically invoked
# The code that follow is required to deal with complex cases with old-style and new-style inits
var auto_super_inits = new Array[CallSite]
# The look for new-style super constructors (called from a old style constructor)
var candidatedefs = get_super_candidatedefs(modelbuilder)
if not candidatedefs.is_empty and auto_super_inits.is_empty then
var candidatedef = candidatedefs.first
if candidatedefs.length > 1 then
var cd2 = candidatedefs[1]
modelbuilder.error(self, "Error: cannot do an implicit constructor call to conflicting inherited inits `{cd2}({cd2.initializers.join(", ")}`) and `{candidatedef}({candidatedef.initializers.join(", ")}`). NOTE: Do not mix old-style and new-style init!")
is_broken = true
return
end
var msignature = candidatedef.msignature
msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
if msignature.arity > mpropdef.msignature.arity then
modelbuilder.error(self, "Error: cannot do an implicit constructor call to `{candidatedef}{msignature}`. Expected at least `{msignature.arity}` arguments.")
is_broken = true
return
end
if candidatedef.mproperty != mpropdef.mproperty then
var i = 0
for candidat_mparameter in msignature.mparameters do
var actual_mparameter = mpropdef.msignature.mparameters[i]
if not candidat_mparameter.mtype.is_subtype(mmodule, anchor, actual_mparameter.mtype) then
modelbuilder.error(self, "Type Error: expected argument #{i} of type `{candidat_mparameter.mtype}`, got implicit argument `{candidat_mparameter.name}` of type `{actual_mparameter.mtype}`. Signature is {msignature}")
return
end
i += 1
end
end
var callsite = new CallSite(hot_location, recvtype, mmodule, anchor, true, candidatedef.mproperty, candidatedef, msignature, false)
auto_super_inits.add(callsite)
modelbuilder.toolcontext.info("Auto-super init for {mpropdef} to {candidatedef.full_name}", 4)
else if candidatedefs.is_empty then
# skip broken
is_broken = true
return
end
if auto_super_inits.is_empty then
modelbuilder.error(self, "Error: no constructors to call implicitly in `{mpropdef}`. Call one explicitly.")
return
end
self.auto_super_inits = auto_super_inits
end
# This method returns the list of possible candidates for the current definition.
#
# Warning this method supports super call from old_style_init to default_inits without signature verification!!!
private fun get_super_candidatedefs(modelbuilder: ModelBuilder): Array[MMethodDef]
do
var candidatedefs = new Array[MMethodDef]
var mclassdef = self.parent.as(AClassdef).mclassdef
if mclassdef == null or mclassdef.is_broken then return candidatedefs # skip error
var mpropdef = self.mpropdef
if mpropdef == null or mpropdef.is_broken then return candidatedefs # skip error
var mmodule = mpropdef.mclassdef.mmodule
var anchor = mclassdef.bound_mtype
var mproperty = mpropdef.mproperty
# The look for new-style super constructors (called from a old style constructor)
var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
if mpropdef.is_old_style_init then
var superprop: nullable MMethodDef = null
for mclass in mclassdef.mclass.in_hierarchy(mmodule).direct_greaters do
candidatedefs.add(mclass.intro.default_init.as(not null))
end
else
candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
end
return candidatedefs
end
end
src/semantize/auto_super_init.nit:49,1--184,3
redef class AMethPropdef
private init make(n_visibility: nullable AVisibility,
tk_redef: nullable TKwredef,
mmethoddef: nullable MMethodDef,
n_signature: nullable ASignature,
n_annotations: nullable AAnnotations,
n_extern_calls: nullable AExternCalls,
n_extern_code_block: nullable AExternCodeBlock,
n_block: nullable AExpr)
do
var n_tid = new TId
var n_methid = new AIdMethid.init_aidmethid(n_tid)
if n_signature == null then n_signature = new ASignature
if n_visibility == null then n_visibility = new APublicVisibility
self.init_amethpropdef(null,tk_redef,n_visibility,new TKwmeth,null,null,null,n_methid,n_signature,n_annotations,n_extern_calls,n_extern_code_block,new TKwdo,n_block,new TKwend)
self.mpropdef = mmethoddef
if mpropdef != null then self.location = mmethoddef.location
end
end
src/astbuilder.nit:403,1--421,3
redef class AMethPropdef
private var foreign_callbacks_cache: nullable ForeignCallbackSet = null
# All foreign callbacks from this method
fun foreign_callbacks: ForeignCallbackSet
do
var fcs = foreign_callbacks_cache
assert fcs != null else print "Error: attempting to access nitni callbacks before phase 'verify_nitni_callback_phase'."
return fcs
end
# Verifiy the validity of the explicit callbacks to Nit
# also fills the set returned by foreign_callbacks
fun verify_nitni_callbacks(toolcontext: ToolContext)
do
if foreign_callbacks_cache != null then return
var fcs = new ForeignCallbackSet
var mmodule = mpropdef.mclassdef.mmodule
# receiver
var recv_type = mpropdef.mclassdef.bound_mtype
fcs.types.add(recv_type)
# return type
var rmt = mpropdef.msignature.return_mtype
if rmt != null then
if rmt isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
rmt = rmt.anchor_to(mmodule, mclass_type)
end
var mtype = rmt.resolve_for(recv_type, recv_type, mmodule, true)
fcs.types.add(mtype)
end
# params
for p in mpropdef.msignature.mparameters do
var mtype = p.mtype.resolve_for(recv_type, recv_type, mmodule, true)
if mtype isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
mtype = mtype.anchor_to(mmodule, mclass_type)
end
fcs.types.add( mtype )
end
# explicit callbacks
if n_extern_calls != null then
for ec in n_extern_calls.n_extern_calls do
ec.verify_and_collect(self, fcs, toolcontext)
end
end
# store result
foreign_callbacks_cache = fcs
end
redef fun accept_rapid_type_visitor(v)
do
if foreign_callbacks_cache == null then return
for cb in foreign_callbacks.callbacks do v.add_send(cb.recv_mtype, cb.mproperty.as(MMethod))
for cast in foreign_callbacks.casts do v.add_cast_type(cast.to)
for sup in foreign_callbacks.supers do
v.analysis.add_super_send(sup.from.mclassdef.mclass.mclass_type, sup.from.as(MMethodDef))
end
for t in foreign_callbacks.types do if t isa MClassType then v.add_type t
end
end
src/nitni/nitni_callbacks.nit:86,1--154,3
redef class AMethPropdef
redef fun verify_nitni_callbacks(toolcontext)
do
super
var block = n_extern_code_block
if block != null and block.is_java then
insert_artificial_callbacks(toolcontext)
end
end
# Insert additional explicit calls to get the current `JNIEnv`
#
# This forces declaration of callbacks to Nit. The callbacks will be available in Java
# but will be used mainly by the FFI itself.
#
# The developer can also customize the JNIEnv used by the FFI by redefining `Sys::jni_env`.
private fun insert_artificial_callbacks(toolcontext: ToolContext)
do
var fcc = foreign_callbacks
var modelbuilder = toolcontext.modelbuilder
var mmodule = mpropdef.mclassdef.mmodule
# We use callbacks from the C FFI since they will be called from generated C
var c_language_visitor = toolcontext.ffi_language_assignation_phase.as(FFILanguageAssignationPhase).c_language
if not mmodule.ffi_callbacks.keys.has(c_language_visitor) then
mmodule.ffi_callbacks[c_language_visitor] = new HashSet[NitniCallback]
end
# Pointer::sys
var pointer_class = modelbuilder.try_get_mclass_by_name(self, mmodule, "Pointer")
assert pointer_class != null
var pointer_sys_meth = modelbuilder.try_get_mproperty_by_name2(self, mmodule, pointer_class.mclass_type, "sys")
assert pointer_sys_meth != null and pointer_sys_meth isa MMethod
var explicit_call = new MExplicitCall(pointer_class.mclass_type, pointer_sys_meth, mmodule)
fcc.callbacks.add(explicit_call)
mmodule.ffi_callbacks[c_language_visitor].add(explicit_call)
# Sys::jni_env
var sys_class = modelbuilder.try_get_mclass_by_name(self, mmodule, "Sys")
assert sys_class != null
var sys_jni_env_meth = modelbuilder.try_get_mproperty_by_name2(self, mmodule, sys_class.mclass_type, "jni_env")
if sys_jni_env_meth == null or not sys_jni_env_meth isa MMethod then
toolcontext.error(self.location, "Java FFI Error: you must import the `java` module when using the FFI with Java")
return
end
explicit_call = new MExplicitCall(sys_class.mclass_type, sys_jni_env_meth, mmodule)
fcc.callbacks.add(explicit_call)
mmodule.ffi_callbacks[c_language_visitor].add(explicit_call)
# Sys::load_jclass
var sys_jni_load_jclass_meth = modelbuilder.try_get_mproperty_by_name2(self, mmodule, sys_class.mclass_type, "load_jclass")
assert sys_jni_load_jclass_meth != null
assert sys_jni_load_jclass_meth isa MMethod
explicit_call = new MExplicitCall(sys_class.mclass_type, sys_jni_load_jclass_meth, mmodule)
fcc.callbacks.add(explicit_call)
mmodule.ffi_callbacks[c_language_visitor].add(explicit_call)
explicit_call.fill_type_for(fcc, mmodule)
end
end
src/ffi/java.nit:317,1--380,3
redef class AMethPropdef
super TablesCapable
redef fun call(v, mpropdef, args)
do
var f = v.new_frame(self, mpropdef, args)
var res = call_commons(v, mpropdef, args, f)
v.frames.shift
if v.is_escape(self.return_mark) then
res = v.escapevalue
return res
end
return res
end
# Execution of the body of the method
#
# It handle the common special cases: super, intern, extern
fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
do
v.frames.unshift(f)
for i in [0..mpropdef.msignature.arity[ do
var variable = self.n_signature.n_params[i].variable
assert variable != null
v.write_variable(variable, arguments[i+1])
end
# Call the implicit super-init
var auto_super_inits = self.auto_super_inits
if auto_super_inits != null then
var args = [arguments.first]
for auto_super_init in auto_super_inits do
args.clear
for i in [0..auto_super_init.msignature.arity+1[ do
args.add(arguments[i])
end
assert auto_super_init.mproperty != mpropdef.mproperty
v.callsite(auto_super_init, args)
end
end
if auto_super_call then
# standard call-next-method
var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
v.call(superpd, arguments)
end
# First, try intern
if mpropdef.is_intern or mpropdef.is_extern then
var res = intern_call(v, mpropdef, arguments)
if res != v.error_instance then return res
end
# Then, try extern
if mpropdef.is_extern then
var res = call_extern(v, mpropdef, arguments, f)
if res != v.error_instance then return res
end
# Else try block
if n_block != null then
v.stmt(self.n_block)
return null
end
# Fail if nothing succeed
if mpropdef.is_intern then
fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
else if mpropdef.is_extern then
fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
else
fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
end
abort
end
# Call this extern method
protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
do
return v.error_instance
end
# Interprets a intern or a shortcut extern method.
# Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
do
var pname = mpropdef.mproperty.name
var cname = mpropdef.mclassdef.mclass.name
if pname == "call" and v.routine_types.has(cname) then
var routine = args.shift
assert routine isa CallrefInstance
# Swap the receiver position with the original recv of the call form.
args.unshift routine.recv
var res = v.callsite(routine.callsite, args)
# recover the old args state
args.shift
args.unshift routine
return res
end
if pname == "output" then
var recv = args.first
recv.val.output
return null
else if pname == "object_id" then
var recv = args.first
if recv isa PrimitiveInstance[Object] then
return v.int_instance(recv.val.object_id)
else
return v.int_instance(recv.object_id)
end
else if pname == "output_class_name" then
var recv = args.first
print recv.mtype
return null
else if pname == "native_class_name" then
var recv = args.first
var txt = recv.mtype.to_s
return v.c_string_instance(txt)
else if pname == "==" then
# == is correctly redefined for instances
return v.bool_instance(args[0] == args[1])
else if pname == "!=" then
return v.bool_instance(args[0] != args[1])
else if pname == "is_same_type" then
return v.bool_instance(args[0].mtype == args[1].mtype)
else if pname == "is_same_instance" then
return v.bool_instance(args[0].eq_is(args[1]))
else if pname == "class_inheritance_metamodel_json" then
return v.c_string_instance(v.mainmodule.flatten_mclass_hierarchy.to_thin_json)
else if pname == "exit" then
exit(args[1].to_i)
abort
else if pname == "buffer_mode_full" then
return v.int_instance(sys.buffer_mode_full)
else if pname == "buffer_mode_line" then
return v.int_instance(sys.buffer_mode_line)
else if pname == "buffer_mode_none" then
return v.int_instance(sys.buffer_mode_none)
else if pname == "sys" then
return v.mainobj
else if cname == "Int" then
var recvval = args[0].to_i
if pname == "unary -" then
return v.int_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.int_instance(recvval + args[1].to_i)
else if pname == "-" then
return v.int_instance(recvval - args[1].to_i)
else if pname == "*" then
return v.int_instance(recvval * args[1].to_i)
else if pname == "%" then
return v.int_instance(recvval % args[1].to_i)
else if pname == "/" then
return v.int_instance(recvval / args[1].to_i)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_i)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_i)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_i)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_i)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i)
else if pname == "&" then
return v.int_instance(recvval & args[1].to_i)
else if pname == "|" then
return v.int_instance(recvval | args[1].to_i)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "<<" then
return v.int_instance(recvval << args[1].to_i)
else if pname == ">>" then
return v.int_instance(recvval >> args[1].to_i)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
end
else if cname == "Byte" then
var recvval = args[0].to_b
if pname == "unary -" then
return v.byte_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.byte_instance(recvval + args[1].to_b)
else if pname == "-" then
return v.byte_instance(recvval - args[1].to_b)
else if pname == "*" then
return v.byte_instance(recvval * args[1].to_b)
else if pname == "%" then
return v.byte_instance(recvval % args[1].to_b)
else if pname == "/" then
return v.byte_instance(recvval / args[1].to_b)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_b)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_b)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_b)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_b)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_b)
else if pname == "&" then
return v.byte_instance(recvval & args[1].to_b)
else if pname == "|" then
return v.byte_instance(recvval | args[1].to_b)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "<<" then
return v.byte_instance(recvval << args[1].to_i)
else if pname == ">>" then
return v.byte_instance(recvval >> args[1].to_i)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
else if pname == "byte_to_s_len" then
return v.int_instance(recvval.to_s.length)
end
else if cname == "Char" then
var recv = args[0].val.as(Char)
if pname == "successor" then
return v.char_instance(recv.successor(args[1].to_i))
else if pname == "predecessor" then
return v.char_instance(recv.predecessor(args[1].to_i))
else if pname == "<" then
return v.bool_instance(recv < args[1].val.as(Char))
else if pname == ">" then
return v.bool_instance(recv > args[1].val.as(Char))
else if pname == "<=" then
return v.bool_instance(recv <= args[1].val.as(Char))
else if pname == ">=" then
return v.bool_instance(recv >= args[1].val.as(Char))
else if pname == "<=>" then
return v.int_instance(recv <=> args[1].val.as(Char))
end
else if cname == "Float" then
var recv = args[0].to_f
if pname == "unary -" then
return v.float_instance(-recv)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.float_instance(recv + args[1].to_f)
else if pname == "-" then
return v.float_instance(recv - args[1].to_f)
else if pname == "*" then
return v.float_instance(recv * args[1].to_f)
else if pname == "/" then
return v.float_instance(recv / args[1].to_f)
else if pname == "<" then
return v.bool_instance(recv < args[1].to_f)
else if pname == ">" then
return v.bool_instance(recv > args[1].to_f)
else if pname == "<=" then
return v.bool_instance(recv <= args[1].to_f)
else if pname == ">=" then
return v.bool_instance(recv >= args[1].to_f)
else if pname == "to_i" then
return v.int_instance(recv.to_i)
else if pname == "to_b" then
return v.byte_instance(recv.to_b)
else if pname == "to_i8" then
return v.int8_instance(recv.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recv.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recv.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recv.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recv.to_u32)
else if pname == "cos" then
return v.float_instance(args[0].to_f.cos)
else if pname == "sin" then
return v.float_instance(args[0].to_f.sin)
else if pname == "tan" then
return v.float_instance(args[0].to_f.tan)
else if pname == "acos" then
return v.float_instance(args[0].to_f.acos)
else if pname == "asin" then
return v.float_instance(args[0].to_f.asin)
else if pname == "atan" then
return v.float_instance(args[0].to_f.atan)
else if pname == "sqrt" then
return v.float_instance(args[0].to_f.sqrt)
else if pname == "exp" then
return v.float_instance(args[0].to_f.exp)
else if pname == "log" then
return v.float_instance(args[0].to_f.log)
else if pname == "pow" then
return v.float_instance(args[0].to_f.pow(args[1].to_f))
else if pname == "abs" then
return v.float_instance(args[0].to_f.abs)
else if pname == "hypot_with" then
return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
else if pname == "is_nan" then
return v.bool_instance(args[0].to_f.is_nan)
else if pname == "is_inf_extern" then
return v.bool_instance(args[0].to_f.is_inf != 0)
else if pname == "round" then
return v.float_instance(args[0].to_f.round)
end
else if cname == "CString" then
if pname == "new" then
return v.c_string_instance_len(args[1].to_i)
end
var recvval = args.first.val.as(CString)
if pname == "[]" then
var arg1 = args[1].to_i
return v.int_instance(recvval[arg1])
else if pname == "[]=" then
var arg1 = args[1].to_i
recvval[arg1] = args[2].val.as(Int)
return null
else if pname == "copy_to" then
# sig= copy_to(dest: CString, length: Int, from: Int, to: Int)
var destval = args[1].val.as(CString)
var lenval = args[2].to_i
var fromval = args[3].to_i
var toval = args[4].to_i
recvval.copy_to(destval, lenval, fromval, toval)
return null
else if pname == "atoi" then
return v.int_instance(recvval.atoi)
else if pname == "fast_cstring" then
return v.c_string_instance_fast_cstr(args[0].val.as(CString), args[1].to_i)
else if pname == "fetch_4_chars" then
return v.uint32_instance(args[0].val.as(CString).fetch_4_chars(args[1].to_i))
else if pname == "fetch_4_hchars" then
return v.uint32_instance(args[0].val.as(CString).fetch_4_hchars(args[1].to_i))
else if pname == "utf8_length" then
return v.int_instance(args[0].val.as(CString).utf8_length(args[1].to_i, args[2].to_i))
end
else if cname == "NativeArray" then
if pname == "new" then
var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
v.init_instance_primitive(instance)
return instance
end
var recvval = args.first.val.as(Array[Instance])
if pname == "[]" then
return recvval[args[1].to_i]
else if pname == "[]=" then
recvval[args[1].to_i] = args[2]
return null
else if pname == "length" then
return v.int_instance(recvval.length)
else if pname == "copy_to" then
recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
return null
end
else if cname == "Int8" then
var recvval = args[0].to_i8
if pname == "unary -" then
return v.int8_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.int8_instance(recvval + args[1].to_i8)
else if pname == "-" then
return v.int8_instance(recvval - args[1].to_i8)
else if pname == "*" then
return v.int8_instance(recvval * args[1].to_i8)
else if pname == "%" then
return v.int8_instance(recvval % args[1].to_i8)
else if pname == "/" then
return v.int8_instance(recvval / args[1].to_i8)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_i8)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_i8)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_i8)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_i8)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i8)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
else if pname == "<<" then
return v.int8_instance(recvval << (args[1].to_i))
else if pname == ">>" then
return v.int8_instance(recvval >> (args[1].to_i))
else if pname == "&" then
return v.int8_instance(recvval & args[1].to_i8)
else if pname == "|" then
return v.int8_instance(recvval | args[1].to_i8)
else if pname == "^" then
return v.int8_instance(recvval ^ args[1].to_i8)
else if pname == "unary ~" then
return v.int8_instance(~recvval)
end
else if cname == "Int16" then
var recvval = args[0].to_i16
if pname == "unary -" then
return v.int16_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.int16_instance(recvval + args[1].to_i16)
else if pname == "-" then
return v.int16_instance(recvval - args[1].to_i16)
else if pname == "*" then
return v.int16_instance(recvval * args[1].to_i16)
else if pname == "%" then
return v.int16_instance(recvval % args[1].to_i16)
else if pname == "/" then
return v.int16_instance(recvval / args[1].to_i16)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_i16)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_i16)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_i16)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_i16)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i16)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
else if pname == "<<" then
return v.int16_instance(recvval << (args[1].to_i))
else if pname == ">>" then
return v.int16_instance(recvval >> (args[1].to_i))
else if pname == "&" then
return v.int16_instance(recvval & args[1].to_i16)
else if pname == "|" then
return v.int16_instance(recvval | args[1].to_i16)
else if pname == "^" then
return v.int16_instance(recvval ^ args[1].to_i16)
else if pname == "unary ~" then
return v.int16_instance(~recvval)
end
else if cname == "UInt16" then
var recvval = args[0].to_u16
if pname == "unary -" then
return v.uint16_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.uint16_instance(recvval + args[1].to_u16)
else if pname == "-" then
return v.uint16_instance(recvval - args[1].to_u16)
else if pname == "*" then
return v.uint16_instance(recvval * args[1].to_u16)
else if pname == "%" then
return v.uint16_instance(recvval % args[1].to_u16)
else if pname == "/" then
return v.uint16_instance(recvval / args[1].to_u16)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_u16)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_u16)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_u16)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_u16)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_u16)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
else if pname == "<<" then
return v.uint16_instance(recvval << (args[1].to_i))
else if pname == ">>" then
return v.uint16_instance(recvval >> (args[1].to_i))
else if pname == "&" then
return v.uint16_instance(recvval & args[1].to_u16)
else if pname == "|" then
return v.uint16_instance(recvval | args[1].to_u16)
else if pname == "^" then
return v.uint16_instance(recvval ^ args[1].to_u16)
else if pname == "unary ~" then
return v.uint16_instance(~recvval)
end
else if cname == "Int32" then
var recvval = args[0].to_i32
if pname == "unary -" then
return v.int32_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.int32_instance(recvval + args[1].to_i32)
else if pname == "-" then
return v.int32_instance(recvval - args[1].to_i32)
else if pname == "*" then
return v.int32_instance(recvval * args[1].to_i32)
else if pname == "%" then
return v.int32_instance(recvval % args[1].to_i32)
else if pname == "/" then
return v.int32_instance(recvval / args[1].to_i32)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_i32)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_i32)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_i32)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_i32)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i32)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
else if pname == "<<" then
return v.int32_instance(recvval << (args[1].to_i))
else if pname == ">>" then
return v.int32_instance(recvval >> (args[1].to_i))
else if pname == "&" then
return v.int32_instance(recvval & args[1].to_i32)
else if pname == "|" then
return v.int32_instance(recvval | args[1].to_i32)
else if pname == "^" then
return v.int32_instance(recvval ^ args[1].to_i32)
else if pname == "unary ~" then
return v.int32_instance(~recvval)
end
else if cname == "UInt32" then
var recvval = args[0].to_u32
if pname == "unary -" then
return v.uint32_instance(-recvval)
else if pname == "unary +" then
return args[0]
else if pname == "+" then
return v.uint32_instance(recvval + args[1].to_u32)
else if pname == "-" then
return v.uint32_instance(recvval - args[1].to_u32)
else if pname == "*" then
return v.uint32_instance(recvval * args[1].to_u32)
else if pname == "%" then
return v.uint32_instance(recvval % args[1].to_u32)
else if pname == "/" then
return v.uint32_instance(recvval / args[1].to_u32)
else if pname == "<" then
return v.bool_instance(recvval < args[1].to_u32)
else if pname == ">" then
return v.bool_instance(recvval > args[1].to_u32)
else if pname == "<=" then
return v.bool_instance(recvval <= args[1].to_u32)
else if pname == ">=" then
return v.bool_instance(recvval >= args[1].to_u32)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_u32)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.int_instance(recvval.to_i)
else if pname == "to_b" then
return v.byte_instance(recvval.to_b)
else if pname == "to_i8" then
return v.int8_instance(recvval.to_i8)
else if pname == "to_i16" then
return v.int16_instance(recvval.to_i16)
else if pname == "to_u16" then
return v.uint16_instance(recvval.to_u16)
else if pname == "to_i32" then
return v.int32_instance(recvval.to_i32)
else if pname == "<<" then
return v.uint32_instance(recvval << (args[1].to_i))
else if pname == ">>" then
return v.uint32_instance(recvval >> (args[1].to_i))
else if pname == "&" then
return v.uint32_instance(recvval & args[1].to_u32)
else if pname == "|" then
return v.uint32_instance(recvval | args[1].to_u32)
else if pname == "^" then
return v.uint32_instance(recvval ^ args[1].to_u32)
else if pname == "unary ~" then
return v.uint32_instance(~recvval)
end
else if pname == "native_argc" then
return v.int_instance(v.arguments.length)
else if pname == "native_argv" then
var txt = v.arguments[args[1].to_i]
return v.c_string_instance(txt)
else if pname == "lexer_goto" then
return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
else if pname == "lexer_accept" then
return v.int_instance(lexer_accept(args[1].to_i))
else if pname == "parser_goto" then
return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
else if pname == "parser_action" then
return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
end
return v.error_instance
end
end
src/interpreter/naive_interpreter.nit:898,1--1553,3
redef class AMethPropdef
redef fun compile_to_c(v, mpropdef, arguments)
do
# Call the implicit super-init
var auto_super_inits = self.auto_super_inits
if auto_super_inits != null then
var args = [arguments.first]
for auto_super_init in auto_super_inits do
assert auto_super_init.mproperty != mpropdef.mproperty
args.clear
for i in [0..auto_super_init.msignature.arity+1[ do
args.add(arguments[i])
end
assert auto_super_init.mproperty != mpropdef.mproperty
v.compile_callsite(auto_super_init, args)
end
end
if auto_super_call then
v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
end
# Try special compilation
if mpropdef.is_intern then
if compile_intern_to_c(v, mpropdef, arguments) then return
end
if mpropdef.is_extern then
if mpropdef.mproperty.is_init then
if compile_externinit_to_c(v, mpropdef, arguments) then return
else
if compile_externmeth_to_c(v, mpropdef, arguments) then return
end
end
# Compile block if any
var n_block = n_block
if n_block != null then
for i in [0..mpropdef.msignature.arity[ do
var variable = self.n_signature.n_params[i].variable.as(not null)
v.assign(v.variable(variable), arguments[i+1])
end
v.stmt(n_block)
return
end
# We have a problem
v.add_raw_throw
var cn = v.class_name_string(arguments.first)
v.add("PRINT_ERROR(\"Runtime error: uncompiled method `%s` called on `%s`. NOT YET IMPLEMENTED\", \"{mpropdef.mproperty.name.escape_to_c}\", {cn});")
v.add_raw_abort
end
redef fun can_inline
do
if self.auto_super_inits != null then return false
var nblock = self.n_block
if nblock == null then return true
if (mpropdef.mproperty.name == "==" or mpropdef.mproperty.name == "!=") and mpropdef.mclassdef.mclass.name == "Object" then return true
if nblock isa ABlockExpr and nblock.n_expr.length == 0 then return true
return false
end
fun compile_intern_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool
do
var pname = mpropdef.mproperty.name
var cname = mpropdef.mclassdef.mclass.name
var ret = mpropdef.msignature.return_mtype
var compiler = v.compiler
# WARNING: we must not resolve the return type when it's a functional type.
# Otherwise, we get a compile error exactly here. Moreover, `routine_ref_call`
# already handles the return type. NOTE: this warning only apply when compiling
# in `semi-global`.
if ret != null and not compiler.all_routine_types_name.has(cname) then
ret = v.resolve_for(ret, arguments.first)
end
if pname != "==" and pname != "!=" then
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
end
if cname == "Int" then
if pname == "output" then
v.add("printf(\"%ld\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(arguments.first)
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "code_point" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
end
else if cname == "Char" then
if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "successor" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "predecessor" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null)))
return true
else if pname == "code_point" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Byte" then
if pname == "output" then
v.add("printf(\"%x\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "ascii" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Bool" then
if pname == "output" then
v.add("printf({arguments.first}?\"true\\n\":\"false\\n\");")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
end
else if cname == "Float" then
if pname == "output" then
v.add("printf(\"%f\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(double){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "succ" then
v.ret(v.new_expr("{arguments[0]}+1", ret.as(not null)))
return true
else if pname == "prec" then
v.ret(v.new_expr("{arguments[0]}-1", ret.as(not null)))
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "CString" then
if pname == "[]" then
v.ret(v.new_expr("(unsigned char)((int){arguments[0]}[{arguments[1]}])", ret.as(not null)))
return true
else if pname == "[]=" then
v.add("{arguments[0]}[{arguments[1]}]=(unsigned char){arguments[2]};")
return true
else if pname == "copy_to" then
v.add("memmove({arguments[1]}+{arguments[4]},{arguments[0]}+{arguments[3]},{arguments[2]});")
return true
else if pname == "atoi" then
v.ret(v.new_expr("atoi({arguments[0]});", ret.as(not null)))
return true
else if pname == "fast_cstring" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "new" then
var alloc = v.nit_alloc(arguments[1].to_s, "CString")
v.ret(v.new_expr("(char*){alloc}", ret.as(not null)))
return true
else if pname == "fetch_4_chars" then
v.ret(v.new_expr("*((uint32_t*)({arguments[0]} + {arguments[1]}))", ret.as(not null)))
return true
else if pname == "fetch_4_hchars" then
v.ret(v.new_expr("(uint32_t)be32toh(*((uint32_t*)({arguments[0]} + {arguments[1]})))", ret.as(not null)))
return true
end
else if cname == "NativeArray" then
return v.native_array_def(pname, ret, arguments)
else if cname == "Int8" then
if pname == "output" then
v.add("printf(\"%\"PRIi8 \"\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == "^" then
v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Int16" then
if pname == "output" then
v.add("printf(\"%\"PRIi16 \"\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == "^" then
v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "UInt16" then
if pname == "output" then
v.add("printf(\"%\"PRIu16 \"\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == "^" then
v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Int32" then
if pname == "output" then
v.add("printf(\"%\"PRIi32 \"\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == "^" then
v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "UInt32" then
if pname == "output" then
v.add("printf(\"%\"PRIu32 \"\\n\", {arguments.first});")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i8" then
v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i16" then
v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_u16" then
v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_i32" then
v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "|" then
v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
return true
else if pname == "^" then
v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
end
else if compiler.all_routine_types_name.has(cname) then
v.routine_ref_call(mpropdef, arguments)
return true
end
if pname == "exit" then
v.add("exit((int){arguments[1]});")
return true
else if pname == "sys" then
v.ret(v.new_expr("glob_sys", ret.as(not null)))
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "is_same_type" then
v.ret(v.is_same_type_test(arguments[0], arguments[1]))
return true
else if pname == "is_same_instance" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "output_class_name" then
var nat = v.class_name_string(arguments.first)
v.add("printf(\"%s\\n\", {nat});")
return true
else if pname == "native_class_name" then
var nat = v.class_name_string(arguments.first)
v.ret(v.new_expr("(char*){nat}", ret.as(not null)))
return true
else if pname == "force_garbage_collection" then
v.add("nit_gcollect();")
return true
else if pname == "native_argc" then
v.ret(v.new_expr("glob_argc", ret.as(not null)))
return true
else if pname == "native_argv" then
v.ret(v.new_expr("glob_argv[{arguments[1]}]", ret.as(not null)))
return true
end
return false
end
# Compile an extern method
# Return `true` if the compilation was successful, `false` if a fall-back is needed
fun compile_externmeth_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool
do
var externname
var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
if at != null and at.n_args.length == 1 then
externname = at.arg_as_string(v.compiler.modelbuilder)
if externname == null then return false
else
return false
end
v.add_extern(mpropdef.mclassdef.mmodule)
var res: nullable RuntimeVariable = null
var ret = mpropdef.msignature.return_mtype
if ret != null then
ret = v.resolve_for(ret, arguments.first)
res = v.new_var_extern(ret)
end
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
if res == null then
v.add("{externname}({arguments.join(", ")});")
else
v.add("{res} = {externname}({arguments.join(", ")});")
res = v.box_extern(res, ret.as(not null))
v.ret(res)
end
return true
end
# Compile an extern factory
# Return `true` if the compilation was successful, `false` if a fall-back is needed
fun compile_externinit_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool
do
var externname
var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
if at != null then
externname = at.arg_as_string(v.compiler.modelbuilder)
if externname == null then return false
else
return false
end
v.add_extern(mpropdef.mclassdef.mmodule)
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
var ret = arguments.first.mtype
var res = v.new_var_extern(ret)
arguments.shift
v.add("{res} = {externname}({arguments.join(", ")});")
res = v.box_extern(res, ret)
v.ret(res)
return true
end
end
src/compiler/abstract_compiler.nit:2623,1--3559,3
redef class AMethPropdef
redef fun generate_basic_blocks(ssa: SSA)
do
basic_block = new BasicBlock
basic_block.first = self
basic_block.last = self
# If the method has a signature
if n_signature != null then
for p in n_signature.n_params do
# Add parameters to the local variables
variables.add(p.variable.as(not null))
p.variable.parameter = true
end
end
# Add the return variable
variables.add(returnvar)
# Add the self variable
if self.selfvariable != null then variables.add(selfvariable.as(not null))
# Recursively goes into the nodes
if n_block != null then
n_block.generate_basic_blocks(ssa, basic_block.as(not null))
is_generated = true
end
end
end
src/ssa.nit:492,1--520,3
redef class AMethPropdef
redef fun compile_intern_to_c(v, mpropdef, arguments)
do
var pname = mpropdef.mproperty.name
var ret = mpropdef.msignature.as(not null).return_mtype
if pname == "class_inheritance_metamodel_json" then
v.add("extern char* nit_class_inheritance_metamodel;")
v.ret(v.new_expr("nit_class_inheritance_metamodel", ret.as(not null)))
return true
end
return super
end
end
src/compiler/compiler_serialization.nit:55,1--68,3
redef class AMethPropdef
# Execute all method verification scope flow and typing.
# It also execute an ast validation to define all parents and all locations
private fun do_all(toolcontext: ToolContext)
do
self.validate
# FIXME: The `do_` usage it is maybe to much (verification...). Solution: Cut the `do_` methods into simpler parts
self.do_scope(toolcontext)
self.do_flow(toolcontext)
self.do_typing(toolcontext.modelbuilder)
end
# Entry point to create a contract (verification of inheritance, or new contract).
redef fun create_contracts(v)
do
v.ast_builder.check_mmodule(mpropdef.mclassdef.mmodule)
v.current_location = self.location
v.is_intro_contract = mpropdef.is_intro
if n_annotations != null then
for n_annotation in n_annotations.n_items do
check_annotation(v,n_annotation)
end
end
if not mpropdef.is_intro and not v.find_no_contract then
self.check_redef(v)
end
# reset the flag
v.find_no_contract = false
end
# Verification of the annotation to know if it is a contract annotation.
# If this is the case, we built the appropriate contract.
private fun check_annotation(v: ContractsVisitor, n_annotation: AAnnotation)
do
if n_annotation.name == "expect" then
if not v.check_usage_expect(mpropdef.mclassdef.mmodule) then return
var exist_contract = mpropdef.mproperty.check_exist_expect
mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.mexpect.as(not null), exist_contract)
else if n_annotation.name == "ensure" then
if not v.check_usage_ensure(mpropdef.mclassdef.mmodule) then return
var exist_contract = mpropdef.mproperty.check_exist_ensure
mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.mensure.as(not null), exist_contract)
else if n_annotation.name == "no_contract" then
# no_contract found set the flag to true
v.find_no_contract = true
end
end
# Verification if the method have an inherited contract to apply it.
private fun check_redef(v: ContractsVisitor)
do
# Check if the method has an attached contract
if not mpropdef.has_contract then
if mpropdef.mproperty.intro.has_contract then
mpropdef.has_contract = true
end
end
end
# Adapt the block to use the contracts
private fun adapt_block_to_contract(v: ContractsVisitor, contract: MContract, n_mpropdef: AMethPropdef)
do
contract.adapt_block_to_contract(v, n_mpropdef)
mpropdef.has_contract = true
n_mpropdef.do_all(v.toolcontext)
end
end
src/contracts.nit:777,1--848,3
redef class AMethPropdef
# Assign a position in the environment to each local variable
# *`vm` The current VirtualMachine
redef fun numbering_variables(vm: VirtualMachine)
do
# The position in the environment
var position = 0
# The `self` variable has the first position
if self.selfvariable != null then
self.selfvariable.position = position
position += 1
end
# Number the parameters
for i in [0..mpropdef.msignature.arity[ do
var variable = self.n_signature.n_params[i].variable
variable.as(not null).position = position
position += 1
end
# Recursively go into the AST nodes to number all local variables
if n_block != null then
position = vm.numbering(self.n_block, position)
end
is_numbering = true
# The size of the environment to create to execute a call to this method
environment_size = position
end
end
src/vm/variables_numbering.nit:119,1--150,3
redef class AMethPropdef
private fun compile_ffi_support_to_c(v: AbstractCompilerVisitor)
do
var mmodule = mpropdef.mclassdef.mmodule
var amodule = v.compiler.modelbuilder.mmodule2node(mmodule)
var mclass_type = mpropdef.mclassdef.bound_mtype
# Declare as extern
var csignature = mpropdef.mproperty.build_csignature(mclass_type, mmodule, "___impl", long_signature, internal_call_context)
v.declare_once("{csignature};")
# FFI part
amodule.ensure_compile_ffi_wrapper
compile_ffi_method(mmodule)
# nitni - Compile missing callbacks
mmodule.ensure_compile_nitni_base(v)
end
# Should we compile the extern method `self`?
#
# Returns false when restricting to the light FFI on methods using callbacks.
fun accept_externmeth: Bool do return true
redef fun compile_externmeth_to_c(v, mpropdef, arguments)
do
# if using the old native interface fallback on previous implementation
if n_extern_code_block == null then return super
if not accept_externmeth then return false
var mmodule = mpropdef.mclassdef.mmodule
mmodule.uses_ffi = true
var mclass_type = mpropdef.mclassdef.bound_mtype
# Outgoing code in compiler
var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
var recv_var: nullable RuntimeVariable = null
var return_mtype = mpropdef.msignature.return_mtype
if return_mtype != null then
return_mtype = return_mtype.anchor_to(mmodule, mclass_type)
recv_var = v.new_var(return_mtype)
end
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
var arguments_for_c = new Array[String]
for a in [0..arguments.length[ do
var arg = arguments[a]
var param_mtype: MType
if a == 0 then
param_mtype = mpropdef.mclassdef.mclass.mclass_type
else param_mtype = mpropdef.msignature.mparameters[a-1].mtype
param_mtype = param_mtype.anchor_to(mmodule, mclass_type)
if param_mtype.is_cprimitive then
arguments_for_c.add(arg.name)
else
v.add("struct nitni_instance* var_for_c_{a};")
v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));")
v.add("var_for_c_{a}->value = {arg.name};")
arguments_for_c.add("var_for_c_{a}")
end
end
if recv_var == null then
v.add("{externname}({arguments_for_c.join(", ")});")
else
assert return_mtype != null
if return_mtype.is_cprimitive then
v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
else
v.add("struct nitni_instance* ret_var;")
v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
v.add("{recv_var} = ret_var->value;")
end
recv_var = v.box_extern(recv_var, return_mtype)
v.ret(recv_var)
end
compile_ffi_support_to_c(v)
return true
end
redef fun compile_externinit_to_c(v, mpropdef, arguments)
do
# if using the old native interface fallback on previous implementation
if n_extern_code_block == null then return super
if not accept_externmeth then return false
var mmodule = mpropdef.mclassdef.mmodule
mmodule.uses_ffi = true
var mclass_type = mpropdef.mclassdef.bound_mtype
var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
var return_mtype = arguments.first.mtype
var recv_var = v.new_var(return_mtype)
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
arguments.shift
var arguments_for_c = new Array[String]
for a in [0..arguments.length[ do
var arg = arguments[a]
var param_mtype: MType
param_mtype = mpropdef.msignature.mparameters[a].mtype
param_mtype = param_mtype.anchor_to(mmodule, mclass_type)
if param_mtype.is_cprimitive then
arguments_for_c.add(arg.name)
else
v.add("struct nitni_instance* var_for_c_{a};")
v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));")
v.add("var_for_c_{a}->value = {arg.name};")
arguments_for_c.add("var_for_c_{a}")
end
end
if return_mtype.is_cprimitive then
v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
else
v.add("struct nitni_instance* ret_var;")
v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
v.add("{recv_var} = ret_var->value;")
end
recv_var = v.box_extern(recv_var, return_mtype)
v.ret(recv_var)
compile_ffi_support_to_c(v)
return true
end
end
src/compiler/compiler_ffi/light.nit:83,1--221,3
redef class AMethPropdef
redef fun compile_ffi_support_to_c(v)
do
super
var mmodule = mpropdef.mclassdef.mmodule
var mainmodule = v.compiler.mainmodule
var ccu = mmodule.nitni_ccu.as(not null)
for mtype in foreign_callbacks.types do
if not mtype.is_cprimitive then
mtype.compile_extern_type(v, ccu)
# has callbacks already been compiled? (this may very well happen with global compilation)
mtype.compile_extern_helper_functions(v, ccu, mmodule.check_callback_compilation(mtype))
end
end
# compile callbacks
for cb in foreign_callbacks.callbacks do
cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb))
end
for cb in foreign_callbacks.supers do
cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb))
end
for cb in foreign_callbacks.casts do
cb.compile_extern_callbacks(v, ccu, mainmodule.check_callback_compilation(cb))
end
# manage nitni callback set
mmodule.foreign_callbacks.join(foreign_callbacks)
end
end
src/compiler/compiler_ffi/compiler_ffi.nit:47,1--81,3
redef class AMethPropdef
redef fun accept_externmeth do return n_extern_calls == null
end
src/compiler/compiler_ffi/light_only.nit:24,1--26,3
redef class AMethPropdef
# Does this method definition use the FFI and is it supported by the interpreter?
#
# * Must use the nested foreign code block of the FFI.
# * Must not have callbacks.
# * Must be implemented in C.
# * Must not have a parameter or return typed with a Nit standard class.
fun supported_by_dynamic_ffi: Bool
do
# If the user specfied `is light_ffi`, it must be supported
var nats = get_annotations("light_ffi")
if nats.not_empty then return true
var n_extern_code_block = n_extern_code_block
if not (n_extern_calls == null and n_extern_code_block != null and
n_extern_code_block.is_c) then return false
for mparam in mpropdef.msignature.mparameters do
if not mparam.mtype.is_cprimitive then
return false
end
end
var return_mtype = mpropdef.msignature.return_mtype
if return_mtype != null and not return_mtype.is_cprimitive then
return false
end
return true
end
end
src/interpreter/dynamic_loading_ffi/on_demand_compiler.nit:33,1--63,3
redef class AMethPropdef
# Handle to the entrypoint of this method in the foreign code library
private var foreign_entry_cache: nullable ForeignCodeEntry = null
redef fun call_extern(v, mpropdef, args, frame)
do
# Fallback the default error if this method is not supported
if not supported_by_dynamic_ffi then return super
var entry = foreign_entry_cache
if entry == null then
# Get handle to foreign code lib
var amodule = v.modelbuilder.mmodule2node(mpropdef.mclassdef.mmodule)
assert amodule != null
var lib = amodule.foreign_code_lib(v)
if lib == null then return v.error_instance
# Get handle to implementation function
entry = lib.dlsym(mpropdef.foreign_lib_entry_cname.to_cstring)
if entry.address_is_null then
print mpropdef.foreign_lib_entry_cname
v.fatal "FFI Error: Cannot find method {mpropdef.name} in foreign code library."
return v.error_instance
end
foreign_entry_cache = entry
end
# Prepare to send args to foreign code lib
var is_init = mpropdef.mproperty.is_init
if is_init then args.shift
var native_args_length = args.length
var native_args = new CallArg(args.length)
var a = 0
if not is_init then
var arg = args[a]
var native_arg = native_args[a]
native_arg.from_static_type(arg, mpropdef.mclassdef.mclass.mclass_type)
a += 1
end
for param in mpropdef.msignature.mparameters do
var arg = args[a]
var native_arg = native_args[a]
native_arg.from_static_type(arg, param.mtype)
a += 1
end
# Allocate memory for the return value
var native_return = new CallArg(1)
var error = entry.call(native_args_length, native_args, native_return)
if error then
v.fatal "FFI Error: Native code library reported an error"
return null
end
# Get the result
var return_mtype = mpropdef.msignature.return_mtype
if is_init then return_mtype = mpropdef.mclassdef.mclass.mclass_type
var return_value
if return_mtype == null then
return_value = null
else
return_value = native_return.to_instance(return_mtype, v)
end
native_args.free
native_return.free
return return_value
end
end
src/interpreter/dynamic_loading_ffi/dynamic_loading_ffi.nit:249,1--323,3
redef class AMethPropdef
redef fun compile_to_java(v, mpropdef, arguments) do
if mpropdef.msignature != null then
var i = 0
for mparam in mpropdef.msignature.as(not null).mparameters do
var variable = n_signature.as(not null).n_params[i].variable
if variable == null then continue
var argvar = v.variable(variable)
v.assign(argvar, v.new_expr("args[{i + 1}]", v.compiler.mainmodule.object_type))
arguments.add(argvar)
i += 1
end
end
# Call the implicit super-init
var auto_super_inits = self.auto_super_inits
if auto_super_inits != null then
var args = [arguments.first]
for auto_super_init in auto_super_inits do
assert auto_super_init.mproperty != mpropdef.mproperty
args.clear
for i in [0..auto_super_init.msignature.arity+1[ do
args.add(arguments[i])
end
assert auto_super_init.mproperty != mpropdef.mproperty
v.compile_callsite(auto_super_init, args)
end
end
if auto_super_call then
v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
end
compile_inside_to_java(v, mpropdef, arguments)
end
# Compile the inside of the method body
private fun compile_inside_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do
# Compile intern methods
if mpropdef.is_intern then
if compile_intern_to_java(v, mpropdef, arguments) then return
v.info("NOT YET IMPLEMENTED compile_intern for {mpropdef}")
v.ret(v.null_instance)
return
end
# Compile block if any
var n_block = n_block
if n_block != null then
v.stmt(n_block)
return
end
end
# Compile an intern method using Java primitives
fun compile_intern_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool do
var pname = mpropdef.mproperty.name
var cname = mpropdef.mclassdef.mclass.name
var ret = mpropdef.msignature.as(not null).return_mtype
if cname == "Int" then
if pname == "output" then
v.add("System.out.println({arguments[0]});")
v.ret(v.null_instance)
return true
else if pname == "object_id" then
v.ret(arguments.first)
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(byte){arguments[0]}", ret.as(not null)))
return true
else if pname == "ascii" then
v.ret(v.new_expr("(char){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Char" then
if pname == "output" then
v.add("System.out.print({arguments[0]});")
v.ret(v.null_instance)
return true
else if pname == "object_id" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "successor" then
v.ret(v.new_expr("(char)({arguments[0]} + {arguments[1]})", ret.as(not null)))
return true
else if pname == "predecessor" then
v.ret(v.new_expr("(char)({arguments[0]} - {arguments[1]})", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "ascii" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Byte" then
if pname == "output" then
v.add("System.out.println({arguments[0]});")
v.ret(v.null_instance)
return true
else if pname == "object_id" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("(byte)({arguments[0]} + {arguments[1]})", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("(byte)({arguments[0]} - {arguments[1]})", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("(byte)(-{arguments[0]})", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "*" then
v.ret(v.new_expr("(byte)({arguments[0]} * {arguments[1]})", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("(byte)({arguments[0]} / {arguments[1]})", ret.as(not null)))
return true
else if pname == "%" then
v.ret(v.new_expr("(byte)({arguments[0]} % {arguments[1]})", ret.as(not null)))
return true
else if pname == "<<" then
v.ret(v.new_expr("(byte)({arguments[0]} << {arguments[1]})", ret.as(not null)))
return true
else if pname == ">>" then
v.ret(v.new_expr("(byte)({arguments[0]} >> {arguments[1]})", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
else if pname == "ascii" then
v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Bool" then
if pname == "output" then
v.add("System.out.println({arguments[0]});")
v.ret(v.null_instance)
return true
else if pname == "object_id" then
v.ret(v.new_expr("{arguments[0]}?1:0", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
end
else if cname == "Float" then
if pname == "output" then
v.add "if({arguments[0]} == Double.POSITIVE_INFINITY) \{"
v.add "System.out.println(\"inf\");"
v.add "\} else if({arguments[0]} == Double.POSITIVE_INFINITY) \{"
v.add "System.out.println(\"-inf\");"
v.add "\} else \{"
var df = v.get_name("df")
v.add "java.text.DecimalFormat {df} = new java.text.DecimalFormat(\"0.000000\");"
v.add "System.out.println({df}.format({arguments[0]}));"
v.add "\}"
v.ret(v.null_instance)
return true
else if pname == "object_id" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "+" then
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "-" then
v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary -" then
v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
return true
else if pname == "unary +" then
v.ret(arguments[0])
return true
else if pname == "succ" then
v.ret(v.new_expr("{arguments[0]} + 1", ret.as(not null)))
return true
else if pname == "prec" then
v.ret(v.new_expr("{arguments[0]} - 1", ret.as(not null)))
return true
else if pname == "*" then
v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
return true
else if pname == "/" then
v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "!=" then
var res = v.equal_test(arguments[0], arguments[1])
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "<" then
v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
return true
else if pname == ">" then
v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
return true
else if pname == "<=" then
v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
return true
else if pname == ">=" then
v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
return true
else if pname == "to_i" then
v.ret(v.new_expr("(int){arguments[0]}", ret.as(not null)))
return true
else if pname == "to_b" then
v.ret(v.new_expr("(byte){arguments[0]}", ret.as(not null)))
return true
end
end
if pname == "exit" then
v.add("System.exit({arguments[1]});")
v.ret(v.null_instance)
return true
else if pname == "sys" then
# TODO singleton
var main_type = v.compiler.mainmodule.sys_type.as(not null)
var sys = main_type.mclass
v.ret(v.new_expr("new RTVal({sys.rt_name}.get{sys.rt_name}())", main_type))
return true
else if pname == "object_id" then
v.ret(v.new_expr("{arguments[0]}.hashCode()", ret.as(not null)))
return true
else if pname == "is_same_type" then
v.ret(v.is_same_type_test(arguments[0], arguments[1]))
return true
else if pname == "is_same_instance" then
v.ret(v.equal_test(arguments[0], arguments[1]))
return true
else if pname == "output_class_name" then
v.add("System.out.println({arguments[0]}.rtclass.class_name);")
v.ret(v.null_instance)
return true
end
return false
end
end
src/compiler/java_compiler.nit:1503,1--1838,3