X-Git-Url: http://nitlanguage.org diff --git a/src/astbuilder.nit b/src/astbuilder.nit index d81ac6b..8644213 100644 --- a/src/astbuilder.nit +++ b/src/astbuilder.nit @@ -19,6 +19,8 @@ intrude import semantize::typing intrude import literal intrude import parser intrude import semantize::scope +intrude import modelbuilder_base +intrude import modelize_property # General factory to build semantic nodes in the AST of expressions class ASTBuilder @@ -157,11 +159,55 @@ class ASTBuilder do return new AReturnExpr.make(expr) end - # Create a callsite with the given `mproperty`. Take the current method `actual_method` as a context - fun create_callsite(modelbuilder: ModelBuilder, actual_method : AMethPropdef, mproperty: MMethod, is_self_call: Bool): CallSite + + # Make a new not + fun make_not(expr: AExpr): ANotExpr + do + return new ANotExpr.make(expr) + end + + # Make a new attribute + fun make_attribute(name: String, + n_type: nullable AType, + n_visibility: nullable AVisibility, + initial_value: nullable AExpr, + n_block: nullable AExpr, + m_attributedef: nullable MAttributeDef, + m_setterdef: nullable MMethodDef, + m_getterdef: nullable MMethodDef): AAttrPropdef + do + return new AAttrPropdef.make(name, n_type, n_visibility, initial_value, n_block, m_attributedef, m_setterdef, m_getterdef) + end + + # Make a new class (AStdClassdef) + fun make_class(mclassdef: nullable MClassDef, + n_visibility: nullable AVisibility, + n_formaldefs : Collection[AFormaldef], + n_extern_code_block : nullable AExternCodeBlock, + n_propdefs : Collection[APropdef], + n_classkind: nullable AClasskind): AStdClassdef + do + return new AStdClassdef.make(mclassdef, n_visibility, n_formaldefs, n_extern_code_block, n_propdefs, n_classkind) + end + + fun make_var(variable: Variable, mtype: MType): AVarExpr + do + return new AVarExpr.make(variable, mtype) + end + + # Make a call assignment i.e `a = 10` + fun make_call_assign(recv: AExpr, callsite: CallSite, n_args: nullable Collection[AExpr], n_value: AExpr): ACallAssignExpr do - var type_visitor = new TypeVisitor(modelbuilder, actual_method.mpropdef.as(not null)) - var callsite = type_visitor.build_callsite_by_property(actual_method, mproperty.intro_mclassdef.bound_mtype, mproperty, is_self_call) + return new ACallAssignExpr.make(recv, callsite, n_args, n_value) + end + + # Build a callsite to call the `mproperty` in the current method `caller_method`. + # `is_self_call` indicate if the method caller is a property of `self` + fun create_callsite(modelbuilder: ModelBuilder, caller_method : AMethPropdef, mproperty: MMethod, is_self_call: Bool): CallSite + do + # FIXME It's not the better solution to call `TypeVisitor` here to build a model entity, but some make need to have a callsite + var type_visitor = new TypeVisitor(modelbuilder, caller_method.mpropdef.as(not null)) + var callsite = type_visitor.build_callsite_by_property(caller_method, mproperty.intro_mclassdef.bound_mtype, mproperty, is_self_call) assert callsite != null return callsite end @@ -252,6 +298,75 @@ class APlaceholderExpr end end +redef class ACallAssignExpr + private init make(recv: AExpr, callsite: CallSite, args: nullable Collection[AExpr], n_value: AExpr) + do + _callsite = callsite + _mtype = callsite.recv + _is_typed = true + var n_args = new AListExprs + if args != null then + n_args.n_exprs.add_all(args) + end + var n_qid = new AQid + n_qid.n_id = new TId + n_qid.n_id.text = callsite.mproperty.name + init_acallassignexpr(recv, n_qid, n_args, new TAssign, n_value) + end +end + +redef class AStdClassdef + private init make(mclassdef: nullable MClassDef, + n_visibility: nullable AVisibility, + n_formaldefs : Collection[Object], + n_extern_code_block : nullable AExternCodeBlock, + n_propdefs : Collection[Object], + n_classkind: nullable AClasskind) + do + if n_visibility == null then n_visibility = new APublicVisibility + if n_classkind == null then n_classkind = new AConcreteClasskind.init_aconcreteclasskind(new TKwclass) + var n_qid = new AQclassid.init_aqclassid(null, new TClassid) + init_astdclassdef(null, null, n_visibility, n_classkind, n_qid, null, n_formaldefs, null, n_extern_code_block, n_propdefs, new TKwend) + _mclassdef = mclassdef + _mclass = mclassdef.mclass + end +end + +redef class AAttrPropdef + + # Create a new `AAttrPropdef` + # Note: By default if the `AVisibility` is not given the visibility is set to public + private init make(name: String, + n_type: nullable AType, + n_visibility: nullable AVisibility, + initial_value: nullable AExpr, + n_block: nullable AExpr, + m_attributedef: nullable MAttributeDef, + m_setterdef: nullable MMethodDef, + m_getterdef: nullable MMethodDef) + do + # Set the model type + if n_type != null then mtype = n_type.mtype + # Define the visibility default is public + if n_visibility == null then n_visibility = new APublicVisibility + init_aattrpropdef(null, null, n_visibility, new TKwvar, new TId, n_type, null, initial_value, null, null , n_block, null) + # Set the name of the attribute + _n_id2.text = name + _mpropdef = m_attributedef + _mreadpropdef = m_getterdef + _mwritepropdef = m_setterdef + if initial_value != null or n_block != null then has_value = true + if m_attributedef != null then self.location = m_attributedef.location + end +end + +redef class ANotExpr + private init make(expr: AExpr) + do + self.init_anotexpr(new TKwnot, expr) + end +end + redef class AReturnExpr private init make(expr: nullable AExpr) do @@ -260,24 +375,17 @@ redef class AReturnExpr end redef class ASuperExpr - private init make(args: nullable Array[AExpr], n_qualified: nullable AQualified) + private init make(args: nullable Array[AExpr], n_qualified: nullable AQualified, mpropdef: nullable MMethodDef) do var n_args = new AListExprs if args != null then n_args.n_exprs.add_all(args) end + _mpropdef = mpropdef self.init_asuperexpr(n_qualified, new TKwsuper, n_args) end end -redef class AParExpr - private init make(expr: AExpr, annotations: nullable AAnnotations) - do - self.location = expr.location - self.init_aparexpr(new TOpar, expr, new TCpar, annotations) - end -end - redef class AOrExpr private init make(right_expr: AExpr, left_expr: AExpr) do @@ -307,11 +415,8 @@ redef class AMethPropdef 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) - - if mmethoddef != null then - self.n_methid.as(AIdMethid).n_id.text = mmethoddef.name - self.mpropdef = mmethoddef - end + self.mpropdef = mmethoddef + if mpropdef != null then self.location = mmethoddef.location end end @@ -325,18 +430,6 @@ redef class AAssertExpr end end -redef class ABlockExpr - private init make - do - self.is_typed = true - end - - redef fun add(expr) - do - n_expr.add expr - end -end - redef class ALoopExpr private init make do @@ -399,26 +492,108 @@ redef class AIfExpr _n_kwelse = new TKwelse _n_else = new ABlockExpr.make self.mtype = mtype - self.is_typed = true + if mtype != null then self.is_typed = true end end redef class AType - private init make + + private init make(t: nullable MType) do var n_id = new TClassid var n_qid = new AQclassid n_qid.n_id = n_id _n_qid = n_qid + _mtype = t + end + + redef fun clone: SELF + do + return new AType.make(mtype) end end +# Primitive type + redef class AIntegerExpr - private init make(value: Int, t: MType) + + private init make(value: nullable Numeric, t: nullable MType) do - self.value = value - self._n_integer = new TInteger # dummy - self.mtype = t + _mtype = t + if t != null then self.is_typed = true + _value = value + _n_integer = new TInteger # dummy + end + + redef fun clone: SELF + do + return new AIntegerExpr.make(value, mtype) + end +end + +redef class AFloatExpr + + private init make(value: nullable Float, t: nullable MType) + do + _mtype = t + if t != null then self.is_typed = true + _value = value + _n_float = new TFloat # dummy + end + + redef fun clone: SELF + do + return new AFloatExpr.make(value, mtype) + end +end + +redef class ATrueExpr + + private init make(t: nullable MType) + do + init_atrueexpr(new TKwtrue, null) + _mtype = t + if t != null then self.is_typed = true + end + + redef fun clone: SELF + do + return new ATrueExpr.make(mtype) + end +end + +redef class AFalseExpr + + private init make(t: nullable MType) + do + init_afalseexpr(new TKwfalse, null) + _mtype = t + if t != null then self.is_typed = true + end + + redef fun clone: SELF + do + return new AFalseExpr.make(mtype) + end +end + +redef class ACharExpr + + # `token_text` represent the real value as it's present in a file not only the char. + # `token_text` is needed if you want to use some methods (for exemple: `prefix`, `suffix` or `is_code_point methods`) + private init make(value: nullable Char, t: nullable MType, token_text: nullable String) + do + _value = value + _mtype = t + _n_char = new TChar + if token_text != null then n_char.text = token_text + if t != null then self.is_typed = true + end + + redef fun clone: SELF + do + var self_clone = new ACharExpr.make(self.value, mtype, n_char.text) + return self_clone end end @@ -443,7 +618,7 @@ redef class ANewExpr end redef class ACallExpr - private init make(recv: AExpr, callsite: CallSite, args: nullable Array[AExpr]) + private init make(recv: AExpr, callsite: nullable CallSite, args: nullable Array[AExpr]) do self._n_expr = recv _n_args = new AListExprs @@ -453,25 +628,74 @@ redef class ACallExpr if args != null then self.n_args.n_exprs.add_all(args) end - self.callsite = callsite - self.mtype = callsite.msignature.return_mtype - self.is_typed = true + + if callsite != null then + self.callsite = callsite + self.mtype = callsite.msignature.return_mtype + self.is_typed = true + end + end +end + +redef class AAsNotnullExpr + private init make(n_expr: AExpr, t: nullable MType) + do + init_aasnotnullexpr(n_expr, new TKwas, null, new TKwnot, new TKwnull, null) + _mtype = t + if t != null then _is_typed = true + end +end + +redef class ANullExpr + + private init make(t: nullable MType) + do + init_anullexpr(new TKwnull, null) + _mtype = t + if t != null then self.is_typed = true + end +end + +redef class ASelfExpr + + private init make(v: nullable Variable, t: nullable MType) + do + init_aselfexpr(new TKwself, null) + _mtype = t + if t != null then is_typed =true + end + + redef fun clone: SELF + do + return new ASelfExpr.make(self.variable, self.mtype) end end +redef class AImplicitSelfExpr + + redef fun clone: SELF + do + var self_clone = new AImplicitSelfExpr.make(variable, mtype) + self_clone.is_sys = is_sys + return self_clone + end +end + + redef class AAttrExpr - private init make(recv: AExpr, attribute: MAttribute, t: MType) + private init make(recv: AExpr, attribute: nullable MAttribute, t: nullable MType) do _n_expr = recv recv.parent = self _n_id = new TAttrid - mproperty = attribute - mtype = t + _mproperty = attribute + _mtype = t + if t != null then _is_typed = true end end redef class AAttrAssignExpr - private init make(recv: AExpr, attribute: MAttribute, value: AExpr) + private init make(recv: AExpr, attribute: nullable MAttribute, value: AExpr) do _n_expr = recv recv.parent = self @@ -479,29 +703,154 @@ redef class AAttrAssignExpr _n_value = value value.parent = self _n_assign = new TAssign - mproperty = attribute - mtype = value.mtype + _mproperty = attribute + _mtype = value.mtype end end redef class AVarExpr - private init make(v: Variable, mtype: MType) + private init make(v: nullable Variable, t: nullable MType) do _n_id = new TId - variable = v - self.mtype = mtype + if v != null then _n_id.text = v.name + _variable = v + _mtype = t + if t != null then is_typed = true end end redef class AVarAssignExpr - private init make(v: Variable, value: AExpr) + private init make(v: nullable Variable, value: AExpr) do _n_id = new TId + if v != null then _n_id.text = v.name _n_value = value value.parent = self _n_assign = new TAssign - variable = v - mtype = value.mtype + _variable = v + _mtype = value.mtype + if _mtype != null then _is_typed = true + end +end + +redef class ASignature + + init make_from_msignature(msignature: MSignature) + do + var nparams = new Array[AParam] + for mparam in msignature.mparameters do + var variable = new Variable(mparam.name) + variable.declared_type = mparam.mtype + n_params.add(new AParam.make(variable, new AType.make(mparam.mtype))) + end + var return_type = null + if msignature.return_mtype != null then return_type = new AType.make(msignature.return_mtype) + init_asignature(null, nparams, null, return_type) + end + + redef fun clone: SELF + do + var ntype = n_type + if ntype != null then ntype = n_type.clone + return new ASignature.init_asignature(null, n_params.clone, null, ntype) + end +end + +redef class AParam + + private init make(v: nullable Variable, t: nullable AType) + do + _n_id = new TId + if v != null then _n_id.text = v.name + _variable = v + _n_type = t + end + + redef fun clone: SELF + do + var ntype = n_type + if ntype != null then ntype = n_type.clone + return new AParam.make(variable, ntype) + end +end + +redef class AFormaldef + + private init make(mparameter: MParameterType, t: AType) + do + _n_id = new TClassid + _n_id.text = mparameter.name + _n_type = t + _mtype = mparameter + end +end + +redef class ABlockExpr + private init make(t: nullable MType) + do + if t != null then + _mtype = t + _is_typed = true + end + end + + redef fun add(expr) + do + n_expr.add expr + expr.parent = self + end + + fun add_all(exprs: Array[AExpr]) + do + for expr in exprs do + add(expr) + end + end + + redef fun clone: SELF + do + var clone = new ABlockExpr.make(mtype) + for expr in self.n_expr do + clone.add(expr.clone) + end + return clone + end +end + +redef class AQclassid + redef fun clone: SELF + do + return new AQclassid.init_aqclassid(n_qualified.clone, n_id) + end +end + +redef class AQualified + redef fun clone: SELF + do + return new AQualified.init_aqualified(n_id.clone, n_classid) + end +end + +redef class AQid + redef fun clone: SELF + do + var clone_n_qualified = n_qualified + if n_qualified != null then clone_n_qualified = n_qualified.clone + return new AQid.init_aqid(clone_n_qualified, n_id.clone) + end +end + +redef class TId + redef fun clone: SELF + do + return new TId.init_tk(location) + end +end + +redef class AParExpr + private init make(expr: AExpr, annotations: nullable AAnnotations) + do + self.init_aparexpr(new TOpar, expr, new TCpar, annotations) end end @@ -516,7 +865,28 @@ class ASTValidationVisitor private var seen = new HashSet[ANode] end +redef class ANodes + super Cloneable + + redef fun clone: SELF + do + var clone_anodes = new ANodes[E](self.parent) + for node in self do + clone_anodes.add(node.clone) + end + return clone_anodes + end +end + redef class ANode + super Cloneable + + redef fun clone: SELF + do + # By default the clone abort to avoid surprises + print "The clone method is not implemented for the `{self.class_name}` class" + abort + end # Recursively validate a AST node. # This ensure that location and parenting are defined and coherent. # @@ -563,8 +933,226 @@ redef class ANode end redef class AAnnotation + redef fun accept_ast_validation(v) do # Do not enter in annotations end + + private init make(n_args : ANodes[AExpr]) + do + _n_visibility = new APublicVisibility + _n_args = n_args + end +end + +redef class MEntity + # Build a ANode from `self` + # + # Allows the creation of an AST node from a model entity. + fun create_ast_representation(astbuilder: nullable ASTBuilder): ANode is abstract +end + +redef class MPropDef + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): APropdef is abstract +end + +redef class MClassDef + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AStdClassdef do + if astbuilder == null then astbuilder = new ASTBuilder(mmodule) + var n_propdefs = new Array[APropdef] + for mpropdef in self.mpropdefs do + n_propdefs.add(mpropdef.create_ast_representation(astbuilder)) + end + var n_formaldefs = new Array[AFormaldef] + for mparameter in self.mclass.mparameters do n_formaldefs.add(mparameter.create_ast_representation(astbuilder)) + + return astbuilder.make_class(self, visibility.create_ast_representation(astbuilder), n_formaldefs, null, n_propdefs, null) + end +end + +redef class MAttributeDef + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AAttrPropdef do + if astbuilder == null then astbuilder = new ASTBuilder(mclassdef.mmodule) + var ntype = null + if self.static_mtype != null then ntype = static_mtype.create_ast_representation(astbuilder) + return astbuilder.make_attribute("_" + self.name, ntype, self.visibility.create_ast_representation(astbuilder), null, null, self, null, null) + end +end + +redef class MMethodDef + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AMethPropdef do + if astbuilder == null then astbuilder = new ASTBuilder(mclassdef.mmodule) + var tk_redef = null + if self.mproperty.intro != self then tk_redef = new TKwredef + var n_signature = if self.msignature == null then new ASignature else self.msignature.create_ast_representation(astbuilder) + return astbuilder.make_method(visibility.create_ast_representation(astbuilder), tk_redef, self, n_signature) + end +end + +redef class MVisibility + fun create_ast_representation(astbuilder: nullable ASTBuilder): AVisibility do + if self.to_s == "public" then + return new APublicVisibility + else if self.to_s == "private" then + return new APrivateVisibility + else if self.to_s == "protected" then + return new AProtectedVisibility + else + return new AIntrudeVisibility + end + end +end + +redef class MSignature + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): ASignature do + var nparams = new Array[AParam] + for mparam in mparameters do nparams.add(mparam.create_ast_representation(astbuilder)) + var return_type = null + if self.return_mtype != null then return_type = self.return_mtype.create_ast_representation(astbuilder) + return new ASignature.init_asignature(null, nparams, null, return_type) + end +end + +redef class MParameter + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AParam do + var variable = new Variable(self.name) + variable.declared_type = self.mtype + return new AParam.make(variable, self.mtype.create_ast_representation(astbuilder)) + end +end + +redef class MParameterType + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AFormaldef do + var n_type = super + return new AFormaldef.make(self, n_type) + end +end + +redef class MType + redef fun create_ast_representation(astbuilder: nullable ASTBuilder): AType do + return new AType.make(self) + end +end + +redef class ModelBuilder + # Try to get MMethod property if exist in the given mclassdef. return new `MMethod` if not exist. + private fun get_mmethod(name: String, mclassdef: MClassDef, visibility: nullable MVisibility): MMethod do + visibility = visibility or else public_visibility + var mproperty = try_get_mproperty_by_name(null, mclassdef, name).as(nullable MMethod) + if mproperty == null then mproperty = new MMethod(mclassdef, name, mclassdef.location, visibility) + return mproperty + end + + # Creation of a new method (AST and model representation) with the given name. + # See `create_method_from_property` for more information. + fun create_method_from_name(name: String, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature, visibility: nullable MVisibility): AMethPropdef do + var mproperty = get_mmethod(name, mclassdef, visibility) + return create_method_from_property(mproperty, mclassdef, is_abstract, msignature) + end + + # Creation of a new method (AST and model representation) with the given MMethod. + # Take care, if `is_abstract == false` the AMethPropdef returned has an empty body (potential error if the given signature has an return type). + fun create_method_from_property(mproperty: MMethod, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature): AMethPropdef do + var m_def = new MMethodDef(mclassdef, mproperty, mclassdef.location) + + if msignature == null then msignature = new MSignature(new Array[MParameter]) + + m_def.msignature = msignature + m_def.is_abstract = true + var n_def = m_def.create_ast_representation + # Association new npropdef to mpropdef + unsafe_add_mpropdef2npropdef(m_def,n_def) + + if not is_abstract then + n_def.mpropdef.is_abstract = false + n_def.n_block = new ABlockExpr.make + end + + return n_def + end + + # Creation of a new attribute (AST and model representation) with the given name. + # See `create_attribute_from_property` for more information. + fun create_attribute_from_name(name: String, mclassdef: MClassDef, mtype: MType, visibility: nullable MVisibility): AAttrPropdef do + if visibility == null then visibility = public_visibility + var mattribute = try_get_mproperty_by_name(null, mclassdef, name) + if mattribute == null then mattribute = new MAttribute(mclassdef, name, mclassdef.location, visibility) + return create_attribute_from_property(mattribute.as(MAttribute), mclassdef, mtype) + end + + # Creation of a new attribute (AST and model representation) with the given MAttribute. + # See `create_attribute_from_propdef` for more information. + fun create_attribute_from_property(mattribute: MAttribute, mclassdef: MClassDef, mtype: MType): AAttrPropdef do + var attribut_def = new MAttributeDef(mclassdef, mattribute, mclassdef.location) + attribut_def.static_mtype = mtype + return create_attribute_from_propdef(attribut_def) + end + + # Creation of a new attribute (AST representation) with the given MAttributeDef. + fun create_attribute_from_propdef(mattribut_def: MAttributeDef): AAttrPropdef + is + expect(mclassdef2node(mattribut_def.mclassdef) != null) + do + var n_attribute = mattribut_def.create_ast_representation + + var nclass = mclassdef2node(mattribut_def.mclassdef) + + n_attribute.location = mattribut_def.location + n_attribute.validate + + nclass.n_propdefs.unsafe_add_all([n_attribute]) + nclass.validate + + n_attribute.build_read_property(self, mattribut_def.mclassdef) + n_attribute.build_read_signature + + mpropdef2npropdef[mattribut_def] = n_attribute + return n_attribute + end + + # Creation of a new class (AST and model representation) with the given name. + # `visibility` : Define the visibility of the method. If it's `null` the default is `public_visibility` + # See `create_class_from_mclass` for more information. + fun create_class_from_name(name: String, super_type: Array[MClassType], mmodule: MModule, visibility: nullable MVisibility): AStdClassdef do + if visibility == null then visibility = public_visibility + var mclass = try_get_mclass_by_name(null, mmodule, name) + if mclass == null then mclass = new MClass(mmodule, name, mmodule.location, new Array[String], concrete_kind, visibility) + return create_class_from_mclass(mclass, super_type, mmodule) + end + + # Creation of a new class (AST and model representation) with the given MClass. + # This method creates a new concrete class definition `MClassDef`, and adds it to the class hierarchy. + # See `create_class_from_mclassdef` for more information. + fun create_class_from_mclass(mclass: MClass, super_type: Array[MClassType], mmodule: MModule): AStdClassdef do + var mclassdef = new MClassDef(mmodule, mclass.mclass_type, mmodule.location) + mclassdef.set_supertypes(super_type) + mclassdef.add_in_hierarchy + + return create_class_from_mclassdef(mclassdef, mmodule) + end + + # Creation of a new class (AST representation) with the given MClassDef. + # Note all the properties of our MClassDef will also generate an AST representation. + # Make an error if the attribute already has a representation in the modelbuilder. + # This method also create the default constructor. + fun create_class_from_mclassdef(mclassdef: MClassDef, mmodule: MModule): AStdClassdef do + var n_classdef = mclassdef.create_ast_representation + n_classdef.location = mclassdef.location + n_classdef.validate + + for n_propdef in n_classdef.n_propdefs do + var mpropdef = n_propdef.mpropdef + assert mpropdef != null + + var p_npropdef = mpropdef2node(mpropdef) + if p_npropdef != null then error(null, "The property `{mpropdef.name}` already has a representation in the AST.") + unsafe_add_mpropdef2npropdef(mpropdef, n_propdef) + end + + process_default_constructors(n_classdef) + unsafe_add_mclassdef2nclassdef(mclassdef, n_classdef) + + return n_classdef + end end