class Example(FooNode): name = Field(type=T.Id) dest_scope = Field(type=T.Id) content = Field(type=T.Id.list) @langkit_property() def has_kw(kw=T.Symbol): """ Return whether "content" contains the ``kw`` keyword. """ return Self.content.map(lambda c: c.symbol).contains(kw) env_spec = EnvSpec( add_env(names=[Self.name.symbol]), add_to_env_kv( key=Self.name.symbol, value=Self, # Check correct behavior when the env argument is null or not (when # it's not, add to the parents' env), and when or_current=True is # passed or not (current = Self's env). dest_env=Let(lambda name=If( Self.has_kw("null_name"), No(T.Symbol), Self.dest_scope.symbol, ): If( Self.has_kw("or_current"), named_env(name, or_current=True), named_env(name), ))), )
def name_parent(): """ Assuming this node can define a named environment, return the syntactic parent node that defines the parent scope for Self. If there is no such node (because Self is in the root list), return null. """ return If( Self.parent.is_null | Not(Self.parent.is_a(T.FooNode.list)) | Self.parent.parent.is_null | Not(Self.parent.parent.is_a(T.DeclarativePart)) | Self.parent.parent.parent.is_null, No(T.FooNode), # All nodes that can define a named environment are supposed to # live in lists (Self.parent is a list), so Self.parent.parent is # supposed to be a declarative part, and finally Self.parent.parent # gets the node that owns that declarative part. Let( lambda owner=Self.parent.parent.parent: If( owner.is_a( T.PackageDecl, T.PackageBody, T.SubpDecl, T.SubpBody, T.SubpBodyDecls, T.PublicPart, T.PrivatePart ), owner.match( lambda pp=T.PublicPart: pp.parent, lambda pp=T.PrivatePart: pp.parent, lambda n: n, ), No(T.FooNode), ) ) )
def test_if(): # define x x = Var( # let's see... maybe 24? 24 ) # call foo return If( # no way! True, # haha If( # second False, # nope 12, # finally! Self.test_cond( # arg x ) ), # hoho 24 )
def get_rebindings(inverse=T.Bool): example_nodes = Var(Self.parent.cast(T.Example.list).as_array) n1 = Var(example_nodes.at(If(inverse, 1, 2))) n2 = Var(example_nodes.at(If(inverse, 2, 1))) return No(T.EnvRebindings).append_rebinding( n1.children_env, n2.children_env, )
def contains_chained(): """ Return whether this pattern contains a value part that is a chained pattern. """ return If(Self.value_part.is_null, False, Self.value_part.is_a(ChainedNodePattern))
class FooNode(ASTNode): pred = Property(True) foo_1 = Property( If(Self.pred, No(T.BarNode), No(T.Literal)).as_bare_entity, public=True )
def quantifier_name(): """ Return the selector's quantifier name. If the name hasn't been explicitly specified, the default quantifier name is 'all'. """ return If(Self.quantifier.is_null, String("all"), Self.quantifier.text)
def binding_name(): """ Return the binding name associated with this selector call, if any. """ return If(Self.binding.is_null, String(""), Self.binding.text)
def body_decl_scope(): """ Assuming this PackageBody is not in the top-level list, return the environment of its PackageDecl that it should reference. """ pkg_decl = Var(Self.lookup_decl_part) return If(pkg_decl.private_part.is_null, pkg_decl.children_env, pkg_decl.private_part.children_env)
def min_depth_expr(): """ If the 'min_depth' arg is set and 'depth" is not set, return the expression for 'min_depth'. If 'depth' is set return its expression. If neither 'depth' or 'min_depth' is set, return a null expression. """ return If(Self.depth_expr.is_null, Self.expr_for_arg(String('min_depth')), Self.depth_expr)
def new_env_names(): """ Return the names for the environment that this package creates. """ # Always register the "regular" name for this package result = Self.full_name # If there is a private part, that's all we need. Otherwise, register # this environment with the name of the private part as well, so that # package bodies can assume there is always a private part. return If( result.length == 0, No(T.Symbol.array), If( Self.private_part.is_null, [result, result.concat(String('.__privatepart'))], [result], ).map(lambda s: s.to_symbol))
def resolve(lhs=T.FooNode.entity, rhs=T.FooNode.entity): eq = Var( All([ NPropagate(Self.v, T.Literal.combiner, Self.lhs.v, Self.rhs.v), Bind(Self.lhs.v, lhs), Bind(Self.rhs.v, rhs), ])) return If(eq.solve, Self.v.get_value, PropertyError(T.FooNode.entity, "unreachable"))
class Scope(Def): error = Field() name = Field() defs = Field() env_spec = EnvSpec( add_to_env(New(T.env_assoc, key=Self.name.symbol, val=Self)), add_env(), do(If(Self.error.as_bool, PropertyError(T.FooNode), No(T.FooNode))), )
def get_initial_env(): """ Assuming this PackageBody cannot define a named environment, return the environment in which this declaration should be registered. """ pkg_decl = Var( Self.parent.children_env.get_first( Self.name.base_name.to_symbol).cast(T.PackageDecl)) return If(pkg_decl.private_part.is_null, pkg_decl.children_env, pkg_decl.private_part.children_env)
def decl_parent_scope_name(): """ If this node can define a named environment (see ``can_have_name``), return the name of its parent scope. Return a null symbol otherwise. """ return If( Self.can_have_name, Self.name_parent.then( lambda np: np.full_name, default_val=Self.self_name.parent_scope_name, ).to_symbol, No(T.Symbol))
class PackageDecl(FooNode): name = Field(type=T.Name) public_part = Field(type=T.PublicPart) private_part = Field(type=T.PrivatePart) @langkit_property(return_type=T.Name) def self_name(): return Self.name @langkit_property(return_type=T.Symbol.array) def new_env_names(): """ Return the names for the environment that this package creates. """ # Always register the "regular" name for this package result = Self.full_name # If there is a private part, that's all we need. Otherwise, register # this environment with the name of the private part as well, so that # package bodies can assume there is always a private part. return If( result.length == 0, No(T.Symbol.array), If( Self.private_part.is_null, [result, result.concat(String('.__privatepart'))], [result], ).map(lambda s: s.to_symbol) ) env_spec = EnvSpec( set_initial_env_by_name( If( Self.is_toplevel, Self.decl_parent_scope_name, No(T.Symbol), ), Self.parent.children_env ), add_to_env_kv(Self.name.base_name.to_symbol, Self), add_env(names=Self.new_env_names) ) @langkit_property(return_type=T.PackageBody.entity, public=True) def body_part(): """ Return the PackageBody node corresponding to this PackageDecl. """ return Self.private_part.then( lambda pp: pp, default_val=Self, ).children_env.get_first('__nextpart').cast(T.PackageBody)
class SubpBodyDecls(DeclarativePart): """ Top-level list of declaration in a subprogam body. """ env_spec = EnvSpec( # The only case where we need a declarative part to have a name is when # it is top-level in subprogram body (A), so that separate subprogram # bodies (B) can use this environment as their initial env. Note that # this case is legal only when that (A) is the syntactic root. add_env(names=If( Self.parent.is_a(T.SubpBody) & Self.parent.parent.is_null, [Self.parent.cast(T.SubpBody).name.scope_name.to_symbol], No(T.Symbol.array), )))
def can_have_name(): """ Return whether this node can define a named environment. """ return If( Self.is_a(PackageDecl, PackageBody, SubpDecl, SubpBody, SubpBodyDecls, PublicPart, PrivatePart), # All nodes that can define a named environment are supposed to # live in lists, so use Self.parent.parent to get the node that # owns that list. Self.parent.is_a(T.FooNode.list) & (Self.parent.parent.is_null | Self.parent.parent.can_have_name), False, )
def internal_mmz_prop(i=T.Int): return If(i == 0, PropertyError(T.Int), i)
def recurse(n=Int): return If(n <= 1, n, Self.recurse(n - 1))
def test_prop(numbers=T.Int.array, c=T.String): return If(c == String("one"), numbers.at(0), numbers.at(1))
def node_for_env(): return If(Self.create_synthetic.as_bool, New(T.DummySyntheticNode), Self)
def evaluate(): return BigIntLiteral(If(Self.left.evaluate < Self.right.evaluate, 1, 0))
class PackageBody(FooNode): name = Field(type=T.Name) decls = Field(type=T.DeclarativePart) @langkit_property(return_type=T.Name) def self_name(): return Self.name @langkit_property(return_type=T.LexicalEnv) def body_decl_scope(): """ Assuming this PackageBody is not in the top-level list, return the environment of its PackageDecl that it should reference. """ pkg_decl = Var(Self.lookup_decl_part) return If( pkg_decl.private_part.is_null, pkg_decl.children_env, pkg_decl.private_part.children_env ) @langkit_property(return_type=T.PackageDecl) def lookup_decl_part(): """ Assuming this PackageBody is not in the top-level list, return the the corresponding package declaration. """ return ( Self.parent.children_env.get_first(Self.name.base_name.to_symbol) .cast(T.PackageDecl).node ) env_spec = EnvSpec( # The initial environment for package bodies is the private part of the # corresponding package specs (or the public part if there is no # private part). set_initial_env_by_name( If( Self.is_toplevel, Self.suffixed_full_name(String('__privatepart')).to_symbol, No(T.Symbol), ), Self.parent.children_env, ), add_to_env_by_name( '__nextpart', Self, If(Self.can_have_name, Self.suffixed_full_name(String('__privatepart')).to_symbol, No(T.Symbol)), Self.body_decl_scope, ), add_env(names=[Self.suffixed_full_name(String('__body')).to_symbol]), reference( Self.cast(FooNode).singleton, through=T.PackageBody.body_decl_scope, cond=Not(Self.is_toplevel), kind=RefKind.prioritary, ), ) @langkit_property(return_type=T.PackageDecl.entity, public=True) def decl_part(): """ Return the PackageDecl node corresponding to this PackageBody. """ env = Var(Self.parent.children_env) return Self.name.resolve(env).cast(T.PackageDecl)
def prop(empty1=Bool, empty2=Bool): arg1 = Var(If(empty1, EmptyEnv, Self.children_env)) arg2 = Var(If(empty2, EmptyEnv, Self.children_env)) return arg1.is_visible_from(arg2)
def me(b=Bool): return FooNodeStruct.new(node=If(b, Entity, No(FooNode.entity)))
def expr_for_arg(name=T.String): return Let( lambda x=Self.args.find(lambda a: a.arg_name.text == name): If(x.is_null, No(Expr), x.expr) )
def foo(): return If(True, Self, Self).then(lambda s: s).as_bare_entity