mparameters.add(mparameter)
end
initializers.add(npropdef.mpropdef.mproperty)
+ npropdef.mpropdef.mproperty.is_autoinit = true
end
if npropdef isa AAttrPropdef then
if npropdef.mpropdef == null then return # Skip broken attribute
# For autoinit attributes, call the reader to force
# the lazy initialization of the attribute.
initializers.add(npropdef.mreadpropdef.mproperty)
+ npropdef.mreadpropdef.mproperty.is_autoinit = true
continue
end
if npropdef.has_value then continue
if msetter == null then
# No setter, it is a old-style attribute, so just add it
initializers.add(npropdef.mpropdef.mproperty)
+ npropdef.mpropdef.mproperty.is_autoinit = true
else
# Add the setter to the list
initializers.add(msetter.mproperty)
+ msetter.mproperty.is_autoinit = true
end
end
end
return
end
- # Search the longest-one and checks for conflict
- var longest = spropdefs.first
- if spropdefs.length > 1 then
- # Check for conflict in the order of initializers
- # Each initializer list must me a prefix of the longest list
- # part 1. find the longest list
- for spd in spropdefs do
- if spd.initializers.length > longest.initializers.length then longest = spd
- end
- # part 2. compare
- for spd in spropdefs do
- var i = 0
- for p in spd.initializers do
- if p != longest.initializers[i] then
- self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
- return
+ # Look at the autoinit class-annotation
+ var autoinit = nclassdef.get_single_annotation("autoinit", self)
+ var noautoinit = nclassdef.get_single_annotation("noautoinit", self)
+ if autoinit != null then
+ # Just throws the collected initializers
+ mparameters.clear
+ initializers.clear
+
+ if noautoinit != null then
+ error(autoinit, "Error: `autoinit` and `noautoinit` are incompatible.")
+ end
+
+ if autoinit.n_args.is_empty then
+ error(autoinit, "Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.")
+ end
+
+ # Get and check each argument
+ for narg in autoinit.n_args do
+ var id = narg.as_id
+ if id == null then
+ error(narg, "Syntax error: `autoinit` expects method identifiers.")
+ return
+ end
+
+ # Search the property.
+ # To avoid bad surprises, try to get the setter first.
+ var p = try_get_mproperty_by_name(narg, mclassdef, id + "=")
+ if p == null then
+ p = try_get_mproperty_by_name(narg, mclassdef, id)
+ end
+ if p == null then
+ error(narg, "Error: unknown method `{id}`")
+ return
+ end
+ if not p.is_autoinit then
+ error(narg, "Error: `{p}` is not an autoinit method")
+ return
+ end
+
+ # Register the initializer and the parameters
+ initializers.add(p)
+ var pd = p.intro
+ if pd isa MMethodDef then
+ # Get the signature resolved for the current receiver
+ var sig = pd.msignature.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mclassdef.mmodule, false)
+ mparameters.add_all sig.mparameters
+ else
+ # TODO attributes?
+ abort
+ end
+ end
+ else if noautoinit != null then
+ if initializers.is_empty then
+ warning(noautoinit, "useless-noautoinit", "Warning: the list of autoinit is already empty.")
+ end
+ # Just clear initializers
+ mparameters.clear
+ initializers.clear
+ else
+ # Search the longest-one and checks for conflict
+ var longest = spropdefs.first
+ if spropdefs.length > 1 then
+ # Check for conflict in the order of initializers
+ # Each initializer list must me a prefix of the longest list
+ # part 1. find the longest list
+ for spd in spropdefs do
+ if spd.initializers.length > longest.initializers.length then longest = spd
+ end
+ # part 2. compare
+ for spd in spropdefs do
+ var i = 0
+ for p in spd.initializers do
+ if p != longest.initializers[i] then
+ self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+ return
+ end
+ i += 1
end
- i += 1
end
end
- end
- # Can we just inherit?
- if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
- self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
- mclassdef.mclass.root_init = longest
- return
- end
+ # Can we just inherit?
+ if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
+ self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
+ mclassdef.mclass.root_init = longest
+ return
+ end
- # Combine the inherited list to what is collected
- if longest.initializers.length > 0 then
- mparameters.prepend longest.new_msignature.mparameters
- initializers.prepend longest.initializers
+ # Combine the inherited list to what is collected
+ if longest.initializers.length > 0 then
+ mparameters.prepend longest.new_msignature.mparameters
+ initializers.prepend longest.initializers
+ end
end
# If we already have a basic init definition, then setup its initializers
# The associated propdef once build by a `ModelBuilder`
var mpropdef: nullable MPROPDEF is writable
- private fun build_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) is abstract
- private fun build_signature(modelbuilder: ModelBuilder) is abstract
- private fun check_signature(modelbuilder: ModelBuilder) is abstract
+ private fun build_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) do end
+ private fun build_signature(modelbuilder: ModelBuilder) do end
+ private fun check_signature(modelbuilder: ModelBuilder) do end
private fun new_property_visibility(modelbuilder: ModelBuilder, mclassdef: MClassDef, nvisibility: nullable AVisibility): MVisibility
do
var mvisibility = public_visibility
has_value = n_expr != null or n_block != null
var atnoinit = self.get_single_annotation("noinit", modelbuilder)
+ if atnoinit == null then atnoinit = self.get_single_annotation("noautoinit", modelbuilder)
if atnoinit != null then
noinit = true
if has_value then
- modelbuilder.error(atnoinit, "Error: `noinit` attributes cannot have an initial value")
+ modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot have an initial value")
return
end
end
module parser_nodes
import location
+import ordered_tree
# Root of the AST class-hierarchy
abstract class ANode
sys.stderr.write "{hot_location} {self.class_name}: {message}\n{hot_location.colored_line("0;32")}\n"
end
+ # Write the subtree on stdout.
+ # See `ASTDump`
+ fun dump_tree
+ do
+ var d = new ASTDump
+ d.enter_visit(self)
+ d.write_to(sys.stdout)
+ end
+
# Parent of the node in the AST
var parent: nullable ANode = null
end
end
+# A helper class to handle (print) Nit AST as an OrderedTree
+class ASTDump
+ super Visitor
+ super OrderedTree[ANode]
+
+ # Reference to the last parent in the Ordered Tree
+ # Is used to handle the initial node parent and workaround possible inconsistent `ANode::parent`
+ private var last_parent: nullable ANode = null
+
+ redef fun visit(n)
+ do
+ var p = last_parent
+ add(p, n)
+ last_parent = n
+ n.visit_all(self)
+ last_parent = p
+ end
+
+ redef fun display(n)
+ do
+ if n isa Token then
+ return "{n.class_name} \"{n.text.escape_to_c}\" @{n.location}"
+ else
+ return "{n.class_name} @{n.location}"
+ end
+ end
+end
# A sequence of nodes
# It is a specific class (instead of using a Array) to track the parent/child relation when nodes are added or removed
do
var res = new Array[AAnnotation]
var nas = n_annotations
- if nas == null then return res
- for na in nas.n_items do
+ if nas != null then for na in nas.n_items do
if na.name != name then continue
res.add(na)
end
+ if self isa AClassdef then for na in n_propdefs do
+ if na isa AAnnotPropdef then
+ if na.name != name then continue
+ res.add na
+ end
+ end
+
return res
end
# The extern block code
var n_extern_code_block: nullable AExternCodeBlock = null is writable
# The `end` keyword
var n_kwend: TKwend is writable, noinit
+ fun n_superclasses: Array[ASuperPropdef] do
+ return [for d in n_propdefs do if d isa ASuperPropdef then d]
+ end
+
redef fun hot_location do return n_id.location
end
var n_type: nullable AType = null is writable
end
- # A super-class. eg `super X`
- class ASuperclass
- super Prod
-
- # The super keyword
- var n_kwsuper: TKwsuper is writable, noinit
-
- # The super-class (indicated as a type)
- var n_type: AType is writable, noinit
- end
-
# The definition of a property
abstract class APropdef
super ADefinition
super AMethPropdef
end
+ class AAnnotPropdef
+ super APropdef
+ super AAnnotation
+ end
+
+ # A super-class. eg `super X`
+ class ASuperPropdef
+ super APropdef
+
+ # The super keyword
+ var n_kwsuper: TKwsuper is writable, noinit
+
+ # The super-class (indicated as a type)
+ var n_type: AType is writable, noinit
+ end
+
+
# Declaration of callbacks for extern methods
class AExternCalls
super Prod
AConcreteClasskind ../src/test_parser.nit:23,1--5
TKwclass "class" ../src/test_parser.nit:23,1--5
TClassid "PrintTreeVisitor" ../src/test_parser.nit:23,7--22
- ASuperclass ../src/test_parser.nit:24,2--14
+ ASuperPropdef ../src/test_parser.nit:24,2--14
+ APublicVisibility ../src/test_parser.nit:24,2
TKwsuper "super" ../src/test_parser.nit:24,2--6
AType ../src/test_parser.nit:24,8--14
TClassid "Visitor" ../src/test_parser.nit:24,8--14
AListExprs ../src/test_parser.nit:116,44
TCpar ")" ../src/test_parser.nit:116,45
ABlockExpr ../src/test_parser.nit:118,4--121,5
- AVardeclExpr ../src/test_parser.nit:118,4--31
+ AVardeclExpr ../src/test_parser.nit:118,4--33
TKwvar "var" ../src/test_parser.nit:118,4--6
TId "f" ../src/test_parser.nit:118,8
TAssign "=" ../src/test_parser.nit:118,10
- ANewExpr ../src/test_parser.nit:118,12--31
+ ANewExpr ../src/test_parser.nit:118,12--33
TKwnew "new" ../src/test_parser.nit:118,12--14
- AType ../src/test_parser.nit:118,16--23
- TClassid "IFStream" ../src/test_parser.nit:118,16--23
- TId "open" ../src/test_parser.nit:118,25--28
- AParExprs ../src/test_parser.nit:118,29--31
- TOpar "(" ../src/test_parser.nit:118,29
- ACallExpr ../src/test_parser.nit:118,30
- AImplicitSelfExpr ../src/test_parser.nit:118,30
- TId "a" ../src/test_parser.nit:118,30
- AListExprs ../src/test_parser.nit:118,30
- TCpar ")" ../src/test_parser.nit:118,31
+ AType ../src/test_parser.nit:118,16--25
+ TClassid "FileReader" ../src/test_parser.nit:118,16--25
+ TId "open" ../src/test_parser.nit:118,27--30
+ AParExprs ../src/test_parser.nit:118,31--33
+ TOpar "(" ../src/test_parser.nit:118,31
+ ACallExpr ../src/test_parser.nit:118,32
+ AImplicitSelfExpr ../src/test_parser.nit:118,32
+ TId "a" ../src/test_parser.nit:118,32
+ AListExprs ../src/test_parser.nit:118,32
+ TCpar ")" ../src/test_parser.nit:118,33
ACallAssignExpr ../src/test_parser.nit:119,4--32
AImplicitSelfExpr ../src/test_parser.nit:119,4
TId "source" ../src/test_parser.nit:119,4--9