plank icon indicating copy to clipboard operation
plank copied to clipboard

add macros or builder syntax

Open aripiprazole opened this issue 4 years ago • 1 comments
trafficstars

Add a syntax to build object that could be cool and powerful, like kotlin dsl or rust macros.

aripiprazole avatar Jan 28 '21 02:01 aripiprazole

I think that could be implemented with macros, as something like kotlin dsl could be more limited, i thought in this model:

  1. 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.

  1. 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): PlankTokenType where T represents your Token enum(#6), and plank token type a common way to represent the colors in ide
  • lex(): [T] where T represents 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
      }
    })
  )
}
  1. The macro should pass a Expr or a Lexer type, if not, the macro should not compile and throw a error in the cli and ide, if you passes Expr(in this case it is not defined yet, but is supposed to be a representation of Expr in 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
}
  1. 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
  )
}
  1. 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.

  1. You might use a interpolation syntax to access any external variable or token, anyway.

  2. 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
  )
}
  1. The macros could be overloaded by the typesystem

aripiprazole avatar Jan 28 '21 02:01 aripiprazole