def run(name, eq_prop): """ Emit and print the errors we get for the below grammar with "expr" as a property in BarNode. """ env = DynamicVariable('env', LexicalEnv) dyn_node = DynamicVariable('dyn_node', T.BazNode) print('== {} =='.format(name)) eq_prop = eval(eq_prop) class FooNode(ASTNode): ref_var = UserField(LogicVar, public=False) type_var = UserField(LogicVar, public=False) class BarNode(FooNode): main_prop = Property( env.bind(Self.node_env, Bind(Self.type_var, Self.ref_var, eq_prop=eq_prop))) @langkit_property(public=True) def wrapper(): _ = Var(Self.main_prop) ignore(_) return Self.as_bare_entity class BazNode(FooNode): prop = Property(12, warn_on_unused=False) prop2 = Property(True, warn_on_unused=False) @langkit_property(warn_on_unused=False) def prop3(_=T.BarNode): return True @langkit_property(warn_on_unused=False, dynamic_vars=[dyn_node]) def prop4(other=T.BazNode.entity): return other.node == dyn_node @langkit_property(warn_on_unused=False) def prop_a(other=T.BazNode.entity): return Self.as_entity == other @langkit_property(warn_on_unused=False, dynamic_vars=[env]) def prop_b(other=T.BazNode.entity): return other.node_env == env grammar = Grammar('main_rule') grammar.add_rules(main_rule=Or( BarNode('example'), BazNode('example'), )) emit_and_print_errors(grammar) print('')
def construct(self): """ Constructs the resolved expression corresponding to this field access. It can be either a field access or a property call. :rtype: FieldAccessExpr """ to_get = self.resolve_field() # If still not found, we have a problem check_source_language( to_get is not None, "Type {} has no '{}' field or property".format( self.receiver_expr.type.dsl_name, self.field)) check_source_language( not to_get.is_internal, '{} is for internal use only'.format(to_get.qualname)) # Check that this property actually accepts these arguments and that # they are correctly typed. input_args = self.arguments or FieldAccess.Arguments([], {}) args = input_args.associate(to_get) assert len(args) == len(to_get.natural_arguments) arg_exprs = [ None if actual is None else construct( actual, formal.type, custom_msg='Invalid "{}" actual{} for {}:'.format( formal.name.lower, ' (#{})'.format(key) if isinstance(key, int) else '', to_get.qualname, ) + ' expected {expected} but got {expr_type}') for (key, actual), formal in zip(args, to_get.natural_arguments) ] # Even though it is redundant with DynamicVariable.construct, check # that the callee's dynamic variables are bound here so we can emit a # helpful error message if that's not the case. if isinstance(self.to_get, PropertyDef): DynamicVariable.check_call_bindings(self.to_get, 'In call to {prop}') ret = FieldAccess.Expr(self.receiver_expr, to_get, arg_exprs, self.is_deref, abstract_expr=self) return ret
from __future__ import absolute_import, division, print_function import itertools from langkit.diagnostics import WarningSet from langkit.dsl import ASTNode, Bool, LexicalEnv, abstract from langkit.expressions import (AbstractProperty, DynamicVariable, Literal, Property, Self) from utils import default_warning_set, emit_and_print_errors warning_set = default_warning_set.with_disabled(WarningSet.unused_bindings) Env = DynamicVariable('env', LexicalEnv) def run(abstract_dyn_vars, concrete_dyn_vars): """ Emit and print the errors we get for the below grammar for the given abstract property/concrete property dynamic variables. """ def fmt_value(dyn_var): if dyn_var is None: return 'default' elif dyn_var == []: return 'no dynamic variable' else: return 'with dynamic variables' print('== abstract: {}, concrete: {} =='.format( fmt_value(abstract_dyn_vars), fmt_value(concrete_dyn_vars)))
from __future__ import absolute_import, division, print_function from langkit.dsl import ASTNode, Field, T from langkit.expressions import DynamicVariable, Property, Self from langkit.parsers import Grammar, Tok from lexer_example import Token from utils import emit_and_print_errors dynvar = DynamicVariable('dynvar', T.FooNode) class FooNode(ASTNode): pass class Example(FooNode): tok = Field() # The "construct" pass on p1 will require the type of p2 and thus trigger # the construction of p2. A bug used to propagate the binding of "dynvar" # from the construction of p1 to p2's. p1 = Property(dynvar.bind(Self, Self.p2).as_bare_entity, public=True) p2 = Property(dynvar) grammar = Grammar('main_rule') grammar.add_rules( main_rule=Example(Tok(Token.Example, keep=True)), )
from __future__ import absolute_import, division, print_function from langkit.dsl import ASTNode, Bool, T from langkit.expressions import DynamicVariable, Literal, Property, Self from langkit.parsers import Grammar from utils import emit_and_print_errors dyn_var = DynamicVariable('dyn_var', Bool) def run(name, expr, calling_expr=True): """ Emit and print the errors we get for the below grammar with "expr" as a property in BarNode. """ print('== {} =='.format(name)) class FooNode(ASTNode): pass class Example(FooNode): p = Property(expr) calling = Property(calling_expr) grammar = Grammar('main_rule') grammar.add_rules(main_rule=Example('example'), ) emit_and_print_errors(grammar) print('')
""" Test that assigning a default value to a dynamic variable: * allows bind-less calls in the property DSL; * generates the expected public API. """ from langkit.dsl import ASTNode, Bool from langkit.expressions import DynamicVariable, Self, langkit_property from utils import build_and_run BoolVar = DynamicVariable('bool_var', Bool) class RootNode(ASTNode): pass class ExampleNode(RootNode): @langkit_property(public=True, dynamic_vars=[(BoolVar, True)]) def prop(): return BoolVar @langkit_property(public=True) def prop2(): return Self.prop build_and_run(lkt_file='expected_concrete_syntax.lkt', py_script='main.py') print('Done')
from __future__ import absolute_import, division, print_function from langkit.dsl import ASTNode, LexicalEnvType, LogicVarType, T, UserField from langkit.expressions import (Bind, DynamicVariable, Property, Self, Var, langkit_property, ignore) from langkit.parsers import Grammar, Or from utils import emit_and_print_errors env = DynamicVariable('env', LexicalEnvType) dyn_node = DynamicVariable('dyn_node', T.BazNode) def run(name, eq_prop): """ Emit and print the errors we get for the below grammar with "expr" as a property in BarNode. """ for dynvar in [env, dyn_node]: dynvar.unfreeze() print('== {} =='.format(name)) eq_prop = eval(eq_prop) class FooNode(ASTNode): ref_var = UserField(LogicVarType, public=False) type_var = UserField(LogicVarType, public=False) class BarNode(FooNode):
from langkit.dsl import ASTNode, LexicalEnv from langkit.expressions import DynamicVariable, Property, Self from utils import emit_and_print_errors Env = DynamicVariable('env', LexicalEnv) def run(expr): """ Emit and print the errors we get for the below grammar for the given "expr" property expression. """ print('== {} =='.format(expr)) class FooNode(ASTNode): pass class ExampleNode(FooNode): token_node = True implicit_prop = Property(Self.as_bare_entity, dynamic_vars=[Env]) prop = Property(expr, public=True) use_implicit_prop = Property( Env.bind(Self.node_env, Self.implicit_prop), public=True )
""" Check that warnings are correctly issued when a dynamic variable is bound but is not used in the expression. """ from __future__ import absolute_import, division, print_function from langkit.dsl import ASTNode, T from langkit.expressions import DynamicVariable, Self, langkit_property from utils import emit_and_print_errors dyn_node = DynamicVariable('dyn_node', T.FooNode) dyn_node_2 = DynamicVariable('dyn_node_2', T.FooNode) class FooNode(ASTNode): @langkit_property(public=True) def test_prop_1(): return dyn_node.bind(Self, Self.helper_1) @langkit_property(public=True) def helper_1(): return True @langkit_property(public=True, dynamic_vars=[dyn_node_2]) def test_prop_2(): return dyn_node.bind(Self, Self.helper_2) @langkit_property(public=True, dynamic_vars=[dyn_node_2])