2017-04-26 1 views
1

javascript를 확장하여 사용자 정의 유형 검사를 추가하고 싶습니다.자바 스크립트 구문을 확장하여 타이핑 추가

예컨대

이 일의 가장 간단한 방법은 무엇입니까
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) 
} 

:에

function test(welcome:string, num:integer:non-zero) { 
    console.log(welcome + num) 
} 

은 컴파일 할 것인가?

은 지금까지 내가 검토 한 : (나는 그것이 내부 재 작성의 일종을 통해 무슨 생각으로 온라인 문서가 최신 모양)

  • sweet.js
  • esprima 및 escodegen (확실하지 sweet.js를 사용하여)를 시작
  • 수동 구문 분석을 사용하여 일반 expressons 모든 다양한 옵션을 평가 한 후
+1

타이프 스크립트를 사용해 보셨습니까? –

+0

귀하의 마지막 "제안"은 당신을 멀리하지 않을 것입니다. 당신은 진지한 "해킹"을하고 있습니다. (저것은 js 문화가 그렇게 부르는 것이라고 생각합니다.) 그래서 무서운 API와 구식 문서가 당신을 놀라게해서는 안됩니다 : –

+0

@AndyLamb 예, 제가 생각한 것 그래도 훨씬 강력하고 표현력이 뛰어납니다. 예를 들어 function (allWages : array [integer : not-negative] : no-empty) ... 그리고 응용 프로그램마다 사용자 정의 검사기가 있습니다. –

답변

1

하는 것이 가장 좋은 해결책이 될 것으로 보인다. 일하기가 여전히 어렵다. (아마도 나는 잘못된 방식으로 일을하고있다.) 누군가가 비슷한 것을하고 싶다면 나의 해결책이 여기에있다.

'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) 
      } 
     } 
    }