plank
plank copied to clipboard
add macros or builder syntax
trafficstars
Add a syntax to build object that could be cool and powerful, like kotlin dsl or rust macros.
I think that could be implemented with macros, as something like kotlin dsl could be more limited, i thought in this model:
- You might use macros with the syntax below:
fun main(argc: Int, argv: **Char): Void {
println!("Hello, world!");
}
println is a macro that accepts strings.
- This model could be used in tooling, to highlight the things in the used ide, the lexer should implement 2 member functions(#3) that could be evaluated in compile time:
highlight(token: T): PlankTokenTypewhereTrepresents your Token enum(#6), and plank token type a common way to represent the colors in idelex(): [T]whereTrepresents your Token enum, and it will be the entry point for the macro.
PS: The sample below uses generic structs that arent yet implemented.
@derive(Lexer) type EmbedLexer;
macro fun embed(lexer: EmbedLexer): Either<EmbedError, Embed> {
// parser impl and return code
}
fun handleMessage(event: DiscordMessageEvent): Void {
event.user.reply(
embed!({
image = "Some url"
field("A", "B") {
inline = false
}
})
)
}
- The macro should pass a
Expror aLexertype, if not, the macro should not compile and throw a error in the cli and ide, if you passesExpr(in this case it is not defined yet, but is supposed to be a representation ofExprin compiler source code) in parameter, the compiler will immediately use the Plank Lexer and Parser and validate the expression like this:
macro fun println(expr: Expr.String): Either<PlankParseError, Void> {
// println impl
}
- You might pass inline llvm in the macros with another "macro", that will be handled by the compiler:
macro fun println(expr: Expr.String): Either<LLVMError, Void> {
return llvm!(
// some llvm inline
)
}
- You might pass inline c++ code with another "macro", that will be handled by the compiler like the sample above:
macro fun println(expr: Expr.String): Either<CPPError, Void> {
return cpp!(
std::cout << ${expr} << std::endl
)
}
You don't need to pass semicolon in the macro 'cause the compiler will do it for you.
-
You might use a interpolation syntax to access any external variable or token, anyway.
-
To access
Exprs values in compile time, you will need another macro like this:
macro fun println(expr: Expr.String): Either<CPPError, Void> {
return cpp!(
std::cout << ${eval!(expr)} << std::endl
)
}
- The macros could be overloaded by the typesystem