Skip to content

提案:函数宏 #36

@Gaubee

Description

@Gaubee

目前js/ts没有关于宏的语法,所以这里并不是提出什么新语法,而只是提供一种取巧的方式来解决大部分问题。

我们可以定义多种宏语法,来对当前的语法进行修饰,从而逐个解决问题

函数宏

最基础的当然是函数宏,函数宏的语法是最简单的,它只需要接收一系列的“参数”(这些参数本质上是表达式)。所以在实际的运行中,我们只需要做简单的函数替换即可:

log(a ? 1 : 2)
// => 替换成
console.log(a ? 1 : 2)
// => 或者替换成
noop(a ? 1 : 2)

所以我们只需要知道某一个函数是宏函数,然后在语法树中对其进行标记,之后的在使用到它的时候触发语法置换即可。

那么根据置换规则,开发者需要先提供一个正常js/ts环境下能使用的代码:

//#funmacro:default KEY
const log = console.log
//#endfunmarco

这里#funmacro:default代表着默认值,它是纯粹的js/ts语法,不会触发宏替换

而后,我们定义置换代码:

//#funmacro:case KEY, "DEV", ["log1", "log"] 
const log_1 = (...fields) => {
   return globalThis.test.logger.log(...fields)
}
//#endfunmarco

//#funmacro:case KEY, "PROD", ["log2", "log"]
const log_2 = (a,...fields) => {
   return console.log(`!!${a}`, ...fields)
}
//#endfunmarco

这里#funmacro:case的参数是用来尝试匹配定义的宏代码:

  1. PROFILE_KEY: string
  2. PROFILE_VALUE: string/regexp
  3. ...RENAME_FUNS
    如果匹配成功,那么:
  4. 原本#funmacro:default的代码会被移除
  5. 之后的同PROFILE_KEY的#funmacro:case的代码不会再触发匹配,会被直接移除代码
  6. RENAME_FUNS会将该宏范围内的代码进行名字匹配并重构,可以定义多个

宏的嵌套

宏可以进行嵌套,但是基于缩进风格,缩进符号为/

//#funmacro:case "RUNTIME", /Web|WebWorker/
import 'web-log-shim';

///#funmacro:case "RUNTIME", "Web", ["log_web", "log"]
const log_web = (...fields)=>console.log(...fields)
///#endfunmarco

///#funmacro:case "RUNTIME", "WebWorker", ["log_web_worker", "log"]
const log_web_worker = (...fields)=>console.log(...fields)
///#endfunmarco

//#endfunmarco

核心技术重点难点

  1. 这一整套技术,核心的就是要在掌握“重构rename”技术,用函数重命名(这里简单的正则替换是做不了的)。
  2. 要注意的是,这里并不负责提供“函数内联”的功能,该功能应该由其它的组件来实现。
  3. 此外还有一个难点,就是对于语言服务器,它是否能正常工作?这个还需要调研

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions