Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static pattern matching #187

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 54 additions & 23 deletions lib/astupdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions lib/typeInference.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
},
"lint-staged": {
"**/*.+(js)": [
"standard --fix",
"git add ."
"standard --fix"
]
},
"author": "Santosh Rajan",
Expand Down
121 changes: 121 additions & 0 deletions test/assert/staticPatternMatching.json
Original file line number Diff line number Diff line change
@@ -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"
}
5 changes: 5 additions & 0 deletions test/src/staticPatternMatching.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bobAt 10 = 'naughty'
bobAt 20 = 'nerdy'

print (bobAt 20)