diff --git a/lib/astupdate.js b/lib/astupdate.js index 58f9790..41b7f07 100644 --- a/lib/astupdate.js +++ b/lib/astupdate.js @@ -44,28 +44,43 @@ const buildDefaultCase = (funcdecl) => { return defaultcase } -const formMultiPatternAst = (funcdecl, patterndecls) => { - const funcdeclbody = { type: 'BlockStatement', body: [] } - const blockstmtbody = { type: 'SwitchStatement', cases: [] } - const [cases, flag] = buildExplicitCases(patterndecls) - const testTempl = funcdecl.declarations[0].init.params[0] - blockstmtbody.discriminant = testTempl +const formMultiPatternAst = (funcDecl, patternDecls) => { + const funcDeclBody = { type: 'BlockStatement', body: [] } + const blockStmtBody = { type: 'SwitchStatement', cases: [] } + const [cases, flag] = buildExplicitCases(patternDecls) + const testTempl = funcDecl.declarations[0].init.params[0] + blockStmtBody.discriminant = testTempl if (flag === true) { const lengthTempl = estemplate.identifier('length') - blockstmtbody.discriminant = estemplate.memberExpression( + blockStmtBody.discriminant = estemplate.memberExpression( testTempl, lengthTempl ).expression } - cases.push(buildDefaultCase(funcdecl)) - blockstmtbody.cases = cases + cases.push(buildDefaultCase(funcDecl)) + blockStmtBody.cases = cases - funcdeclbody.body.push(blockstmtbody) + funcDeclBody.body.push(blockStmtBody) - funcdecl.declarations[0].init.body = funcdeclbody - funcdecl.declarations[0].init.expression = false + funcDecl.declarations[0].init.body = funcDeclBody + funcDecl.declarations[0].init.expression = false - return funcdecl + return funcDecl +} + +const formStaticPatternAst = (patternDecls) => { + const funcDeclBody = { type: 'BlockStatement', body: [] } + const blockStmtBody = { type: 'SwitchStatement', cases: [] } + const [cases] = buildExplicitCases(patternDecls) + blockStmtBody.cases = cases + const param = estemplate.identifier('x') + blockStmtBody.discriminant = param + funcDeclBody.body.push(blockStmtBody) + return estemplate.funcDeclaration( + estemplate.identifier(functionName(patternDecls[0])), + [param], + funcDeclBody + ) } const isArrowFuncDecl = (decl) => { @@ -97,20 +112,35 @@ const isFunction = (decl) => { return isFunc } -const formFunctionAst = (funcdecl, patterndecls) => { - const patternscount = patterndecls.length - return patternscount === 0 - ? funcdecl - : formMultiPatternAst(funcdecl, patterndecls) +const functionName = (decl = {}) => { + const declarations = decl.declarations || null + if (!declarations) return null + const name = declarations[0].id.name + return name +} + +const formFunctionAst = (funcDecl, patternDecls) => { + const patternsCount = patternDecls.length + return patternsCount === 0 + ? funcDecl + : formMultiPatternAst(funcDecl, patternDecls) } -const processSubTree = (decl) => { +const processSubTree = (decl, nextDecl) => { if (isArrowFuncDecl(decl)) { if (isFunction(decl)) { // function declarations - const funcast = formFunctionAst(decl, patterns) + const funcAst = formFunctionAst(decl, patterns) + patterns = [] + return funcAst + } else if (patterns.length > 0 && + (!nextDecl || functionName(nextDecl) !== functionName(patterns[0])) + ) { + // static patten matching without variable + patterns.push(decl) + const patternFuncAst = formStaticPatternAst(patterns) patterns = [] - return funcast + return patternFuncAst } else { // pattern matched function declarations patterns.push(decl) @@ -123,8 +153,9 @@ const processSubTree = (decl) => { const updateAst = (ast) => { let newBody = [] const declarations = ast.body - declarations.forEach((decl) => { - const subtree = processSubTree(decl) + declarations.forEach((decl, i) => { + const nextDecl = declarations[i + 1] || null + const subtree = processSubTree(decl, nextDecl) if (subtree !== null) newBody.push(subtree) }) newBody = updateComment(newBody) diff --git a/lib/typeInference.js b/lib/typeInference.js index b3d2609..8341164 100644 --- a/lib/typeInference.js +++ b/lib/typeInference.js @@ -44,11 +44,11 @@ const unaryExprType = (expr) => { const getType = (expr, expectedType, localTypeObj, id) => { if (expr !== undefined) { const type = exprType(expr, localTypeObj, id) - return type === expectedType || expectedType === 'bool' + return type === expectedType || + expectedType === 'bool' || + type === 'needsInference' ? type - : type === 'needsInference' - ? type - : null + : null } } diff --git a/package.json b/package.json index 85a4671..29f321b 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,7 @@ }, "lint-staged": { "**/*.+(js)": [ - "standard --fix", - "git add ." + "standard --fix" ] }, "author": "Santosh Rajan", diff --git a/test/assert/staticPatternMatching.json b/test/assert/staticPatternMatching.json new file mode 100644 index 0000000..7fffaa1 --- /dev/null +++ b/test/assert/staticPatternMatching.json @@ -0,0 +1,121 @@ +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "bobAt" + }, + "init": { + "type": "ArrowFunctionExpression", + "id": null, + "params": [ + { + "type": "Identifier", + "name": "x" + } + ], + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "SwitchStatement", + "discriminant": { + "type": "Identifier", + "name": "x" + }, + "cases": [ + { + "type": "SwitchCase", + "test": { + "type": "Literal", + "value": 10, + "raw": "10", + "sType": "number" + }, + "consequent": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Literal", + "value": "naughty", + "raw": "naughty", + "sType": "string" + } + } + ] + }, + { + "type": "SwitchCase", + "test": { + "type": "Literal", + "value": 20, + "raw": "20", + "sType": "number" + }, + "consequent": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Literal", + "value": "nerdy", + "raw": "nerdy", + "sType": "string" + } + } + ] + } + ] + } + ] + }, + "generator": false, + "expression": false + } + } + ], + "kind": "const" + }, + { + "type": "ExpressionStatement", + "expression": { + "sType": "IO", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "computed": false, + "object": { + "type": "Identifier", + "name": "console" + }, + "property": { + "type": "Identifier", + "name": "log" + } + }, + "arguments": [ + { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "bobAt" + }, + "arguments": [ + { + "type": "Literal", + "value": 20, + "raw": "20", + "sType": "number" + } + ] + } + ] + } + } + ], + "sourceType": "script" +} diff --git a/test/src/staticPatternMatching.cl b/test/src/staticPatternMatching.cl new file mode 100644 index 0000000..33737e5 --- /dev/null +++ b/test/src/staticPatternMatching.cl @@ -0,0 +1,5 @@ +bobAt 10 = 'naughty' +bobAt 20 = 'nerdy' + +print (bobAt 20) +