Package: kahmi-dsl
kahmi-dslThis is a Python-based configuration language for theKahmibuild system that is heavily inspired by Groovy and Gradle.Example:buildscript{dependencies=["kahmi-git","kahmi-cxx"]}letcxx=load("kahmi-cxx")letgit=load("kahmi-git")name="myproject"version=git.version()cxx.build("main"){srcs=glob("src/*.cpp")type="executable"}Syntax & SemanticsThe Kahmi DSL is not a strict superset of the Python language, instead it wraps Python code and
swaps between DSL parsing and Python code parsing.Kahmi DSL SyntaxDefine a local variable with theletKeywordLocal variables are defined using theletkeyword. The variable can then be addressed in
Python expressions or as call block targets (see below). The right hand side of the assignment
must be a Python expression.letmy_variable=42Set a property on the current context objectThe same syntax but without theletkeyword assigns the value to a member of the current
context object instead of to a local variable.nmae="my-project"version=git.version()Configure blocksA configure block basically generates a Python function, called the "closure", and passes it
to the specified target. The closure that is defined after the target is passed to the target
by either calling it'sconfigure()method or calling the target directly.print("Hello, World!")# Call without bodybuildscript{dependencies=["kahmi-python"]}cxx.build("main"){srcs=glob("src/*.cpp")}At the root level, every Kahmi script is basically a closure that is executed against the
main context object.Python Syntax ExtensionsWhen parsing a Python expression, Kahmi injects support for multi-line lambdas and macros.Multi-line lambdasThe Kahmi DSL parser injects the ability to define multi-line lambdas in any Python
expression. The lambda syntax is inspired by Javascript/Typescript and uses=>as
the lambda arrow operation to connect the argument definition with the lambda body.A lambda with braces requires a return statement, otherwhise the return value of the
lambda will beNone. Single-statement lambdas are not currently supported with this
syntax (although you can always fall back to standard syntaxlambda: <expr>).letmyFunc=()=>{importrandomreturnrandom.random()}print(myFunc())Nesting lambdas is supported and has the expected semantics except if used in comprehensions
(as they introduce a new scope that can not be captured by the function definition that is
a multi-line lambda is transpiled to).MacrosMacros are plugins that can be enabled in the Kahmi DSL parser to implement custom parsing
logic following a macro identifier. The Kahmi DSL parser comes with a YAML plugin out of the
box:buildscript{dependencies=!yaml{-kahmi-git-kahmi-python}}Dynamic name lookupNames are resolved slightly different in Kahmi Python expressions. The local scope will always
be resolved first. Subsequently, the current context object's members are checked, then the
parent closure's local variables and context object, etc. Then finally, the global variables
and builtins.dependencies=["kahmi-python"]print(dependencies)print('dependencies'inlocals())print('dependencies'invars(self))Explanation: The property assignment sets thedependenciesattribute on the current
context object. Looking up the variable will first search it in the locals, but not find it
there and subsequently find it in the context object (also referrable to asself).Built-insKahmi only provides two additional built-in functions on top of what is provided by Python, and
they are only necessary for the execution of Kahmi's generated Python code.NameDescriptionselfThe root context object for the script.__lookup__(name, locals_, ctx)Helper function to resolve the targets of call blocks.Under the hoodKahmi comes with a simple cli that allows you to run any Kahmi script, but given the limited
ability to override the root context object it is expected that it does not serve much use outside
of debugging and development.$ python -m kahmi.dsl examples/hello.kmiUsing the-Eoption, you can retrieve the Python code that a Kahmi file is transpiled to. This
is especially useful to understand how Kahmi constructs are converted into Python. Below are some
examples:letmsg=(name)=>{return'Hello, '+name}('World')print(msg)deflambda_stdin_1_10(name):return'Hello, '+namemsg=lambda_stdin_1_10('World')__runtime__['print'](msg)buildscript{dependencies=["kahmi-python"]}@__runtime__.closure()def__configure_buildscript(self):__runtime__.set_object_property(self,'dependencies',['kahmi-python'])__configure_buildscript_self_target=__runtime__['buildscript']with__runtime__.pushing(__runtime__['locals']()):__runtime__.configure_object(__configure_buildscript_self_target,__configure_buildscript)Copyright © 2021 Niklas Rosenstein