扩展Javascript语法以添加类型
我想扩展javascript以添加自定义类型检查 e、 g 这将汇编成:扩展Javascript语法以添加类型,javascript,sweet.js,esprima,Javascript,Sweet.js,Esprima,我想扩展javascript以添加自定义类型检查 e、 g 这将汇编成: function test(welcome, num) { if(Object.prototype.toString.call(welcome) !== "[object String]") { throw new Error('welcome must be a string') } if (!Number.isInteger(num)) { throw new
function test(welcome, num) {
if(Object.prototype.toString.call(welcome) !== "[object String]") {
throw new Error('welcome must be a string')
}
if (!Number.isInteger(num)) {
throw new Error('num must be an integer')
}
console.log(welcome + num)
}
最直接的方法是什么
到目前为止,我已经看到:
- sweet.js(在线文档看起来过时了,因为我认为它正在进行某种内部重写)
- esprima和escodegen(不确定从哪里开始)
- 使用正则表达式手动解析
'use strict'
syntax function = function(ctx) {
let funcName = ctx.next().value;
let funcParams = ctx.next().value;
let funcBody = ctx.next().value;
//produce the normal params array
var normalParams = produceNormalParams(funcParams)
//produce the checks
var paramChecks = produceParamChecks(funcParams)
//produce the original funcBody code
//put them together as the final result
var params = ctx.contextify(funcParams)
var paramsArray = []
for (let stx of params) {
paramsArray.push(stx)
}
var inner = #``
var innerStuff = ctx.contextify(funcBody)
for (let item of innerStuff) {
inner = inner.concat(#`${item}`)
}
var result = #`function ${funcName} ${normalParams} {
${paramChecks}
${inner}
}`
return result
function extractParamsAndParamChecks(paramsToken) {
var paramsContext = ctx.contextify(paramsToken)
//extracts the actual parameters
var paramsArray = []
var i = 0;
var firstItembyComma = true
for (let paramItem of paramsContext) {
if (firstItembyComma) {
paramsArray.push({
param: paramItem,
checks: []
})
firstItembyComma = false
}
if (paramItem.value.token.value === ',') {
firstItembyComma = true
i++
} else {
paramsArray[i].checks.push(paramItem.value.token.value)
}
}
for (var i = 0; i < paramsArray.length; i++) {
var checks = paramsArray[i].checks.join('').split(':')
checks.splice(0, 1)
paramsArray[i].checks = checks
}
return paramsArray
}
function produceNormalParams(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
//Produces the final params #string
var inner = #``
var first = true
for (let item of paramsArray) {
if (first === true) {
inner = inner.concat(#`${item.param}`)
} else {
inner = inner.concat(#`,${item.param}`)
}
}
return #`(${inner})`
}
function produceParamChecks(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
var result = #``
for (let paramObject of paramsArray) {
var tests = produceChecks(paramObject)
result = result.concat(#`${tests}`)
}
return result
}
function produceChecks(paramObject) {
var paramToken = paramObject.param
var itemType = paramObject.checks[0]
var checks = paramObject.checks
if (itemType === undefined) return #``
if (itemType === 'array') {
return #`if (Object.prototype.toString.call(${paramToken}) !== "[object Array]") throw new Error('Must be array:' + ${paramToken})`
else {
throw new Error('item type not recognised: ' + itemType)
}
}
}
“使用严格的”
语法函数=函数(ctx){
让funcName=ctx.next().value;
设funcParams=ctx.next().value;
设funcBody=ctx.next().value;
//生成普通参数数组
var normalParams=produceNormalParams(funcParams)
//出示支票
var paramChecks=produceParamChecks(funcParams)
//生成原始的主体代码
//把它们放在一起作为最终结果
var params=ctx.contextify(funcParams)
var paramsArray=[]
for(设参数的stx){
paramsArray.push(stx)
}
内部变量=#``
var innerStuff=ctx.contextify(functbody)
对于(让项目的内部内容){
inner=inner.concat(#`${item}`)
}
var result=#`function${funcName}${normalParams}{
${paramChecks}
${inner}
}`
返回结果
函数提取参数和参数检查(paramsToken){
var paramsContext=ctx.contextify(paramsToken)
//提取实际参数
var paramsArray=[]
var i=0;
var firstItembyComma=true
for(让paramsContext中的param项){
if(firstItembyComma){
推({
参数:参数项,
支票:[]
})
firstItembyComma=false
}
如果(paramItem.value.token.value===','){
firstItembyComma=true
我++
}否则{
paramsArray[i].checks.push(paramItem.value.token.value)
}
}
对于(var i=0;i
你考虑过typescript吗?你上一次的“建议”不会让你走多远。你打算进行一些严重的“黑客攻击”(我想这就是js文化所说的),所以可怕的API和过时的文档不应该吓到你:)@AndyLamb是的,我已经考虑过了,不过我想到的功能要强大得多,表达力也要强得多。例如函数(所有工资:数组[整数:非负]:无空)…然后每个应用程序都有自定义检查程序。@BartekBanachewicz正则表达式解决方案很复杂。。特别是在尝试处理多个开括号,以及确定在何处插入替换代码方面。…这就是为什么我对尝试使用sweet.js/esprima/escodegen进行工作感兴趣的原因(sweet.js显然在幕后使用了escodegen)在动态类型语言中,强制类型通常由测试框架处理。
'use strict'
syntax function = function(ctx) {
let funcName = ctx.next().value;
let funcParams = ctx.next().value;
let funcBody = ctx.next().value;
//produce the normal params array
var normalParams = produceNormalParams(funcParams)
//produce the checks
var paramChecks = produceParamChecks(funcParams)
//produce the original funcBody code
//put them together as the final result
var params = ctx.contextify(funcParams)
var paramsArray = []
for (let stx of params) {
paramsArray.push(stx)
}
var inner = #``
var innerStuff = ctx.contextify(funcBody)
for (let item of innerStuff) {
inner = inner.concat(#`${item}`)
}
var result = #`function ${funcName} ${normalParams} {
${paramChecks}
${inner}
}`
return result
function extractParamsAndParamChecks(paramsToken) {
var paramsContext = ctx.contextify(paramsToken)
//extracts the actual parameters
var paramsArray = []
var i = 0;
var firstItembyComma = true
for (let paramItem of paramsContext) {
if (firstItembyComma) {
paramsArray.push({
param: paramItem,
checks: []
})
firstItembyComma = false
}
if (paramItem.value.token.value === ',') {
firstItembyComma = true
i++
} else {
paramsArray[i].checks.push(paramItem.value.token.value)
}
}
for (var i = 0; i < paramsArray.length; i++) {
var checks = paramsArray[i].checks.join('').split(':')
checks.splice(0, 1)
paramsArray[i].checks = checks
}
return paramsArray
}
function produceNormalParams(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
//Produces the final params #string
var inner = #``
var first = true
for (let item of paramsArray) {
if (first === true) {
inner = inner.concat(#`${item.param}`)
} else {
inner = inner.concat(#`,${item.param}`)
}
}
return #`(${inner})`
}
function produceParamChecks(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
var result = #``
for (let paramObject of paramsArray) {
var tests = produceChecks(paramObject)
result = result.concat(#`${tests}`)
}
return result
}
function produceChecks(paramObject) {
var paramToken = paramObject.param
var itemType = paramObject.checks[0]
var checks = paramObject.checks
if (itemType === undefined) return #``
if (itemType === 'array') {
return #`if (Object.prototype.toString.call(${paramToken}) !== "[object Array]") throw new Error('Must be array:' + ${paramToken})`
else {
throw new Error('item type not recognised: ' + itemType)
}
}
}