Skip to content

Commit

Permalink
Source Mapping
Browse files Browse the repository at this point in the history
commit 3c6d64b
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 20:51:17 2017 -0400

    SourceMapping for IfExpressions

commit 8523796
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 19:56:01 2017 -0400

    Source mapping for `import`s

commit cf656d6
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 19:43:06 2017 -0400

    Source mapping for NamedArrowMemberExpr

commit 3126c1f
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 19:36:08 2017 -0400

    Sourcemaps for safe-await-arrow

commit ed82782
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 19:13:31 2017 -0400

    Source mapping for comprehensions

commit 49290be
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 18:42:54 2017 -0400

    Misc nodeType fixes

commit ee93ac2
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 17:53:22 2017 -0400

    Source mapping for `for-in`

commit 966dc9f
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sun Jun 18 17:53:11 2017 -0400

    Update ast-loc-utils

commit 66dcb7a
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sat Jun 17 23:20:15 2017 -0400

    Source mapping for safe exprs (wip)

commit e957b42
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sat Jun 17 22:58:51 2017 -0400

    Source mapping for functions

commit d07bc5d
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sat Jun 17 22:47:11 2017 -0400

    Source maps: existential

commit d96a1eb
Author: William C. Johnson <wcjohnson@oigroup.net>
Date:   Sat Jun 17 22:23:39 2017 -0400

    Source maps for `~`
  • Loading branch information
wcjohnson committed Jun 19, 2017
1 parent bd67b73 commit b93a9e2
Show file tree
Hide file tree
Showing 80 changed files with 517 additions and 763 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"dependencies": {
"@oigroup/babylon-lightscript": "2.0.0-beta.9",
"@oigroup/lightscript-runtime": "^0.1.0",
"ast-loc-utils": "^1.0.3",
"ast-loc-utils": "^1.1.0",
"babel-types": "^6.24.0"
},
"files": [
Expand Down
22 changes: 20 additions & 2 deletions src/blocks.lsc
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import t from './types'
import is, { isa } from './is'

import getLoc from 'ast-loc-utils/lib/getLoc'
import buildAtLoc from 'ast-loc-utils/lib/buildAtLoc'
import { getLoc, buildAtLoc, getSurroundingLoc, placeAtLoc as atLoc } from 'ast-loc-utils'

export toBlockStatement(body) ->
bodyLoc = getLoc(body)
Expand Down Expand Up @@ -60,3 +59,22 @@ export getScopeParent(path) ->
path.findParent((path) ->
path.isFunction() or path.isBlockStatement() or path.isProgram()
)

export iife(body, async = false) ->
actualBody = if Array.isArray(body):
bodyLoc = getSurroundingLoc(body)
t.blockStatement(body)~atLoc(bodyLoc)
else:
body~toBlockStatement()

loc = actualBody~getLoc()

t.callExpression(
t.arrowFunctionExpression(
[]
actualBody
async
)~atLoc(loc)
[]
)~atLoc(loc)

17 changes: 17 additions & 0 deletions src/compilerState.lsc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { initializeRuntime } from './runtime'
import { insertImports } from './imports'
import { getInlinedOperatorsEnabled } from './inlinedOperators'

import { getLoc, span } from 'ast-loc-utils'

// Singleton object, unique per Program traversal, holding relevant state.
let compilerState = {
// DI Babel instance. Avoid unless necessary; prefer types.lsc
Expand All @@ -13,6 +15,9 @@ let compilerState = {
// Root program path
programPath: null

// Location mixin representing the first character in the file.
firstLoc: null

// Babel Plugin options
opts: null

Expand Down Expand Up @@ -59,6 +64,18 @@ processFilename(state): void ->
export createCompilerState(initialState) ->
now compilerState = initialState
processFilename(compilerState)

// Get zero-location
body = initialState?.programPath?.node?.body
if body and body.length > 0:
initialState.firstLoc = getLoc(body[0])~span(1)
else:
initialState.firstLoc = {
start: 0
end: 1
loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } }
}

return compilerState

export initializeCompilerState() ->
Expand Down
162 changes: 122 additions & 40 deletions src/comprehension.lsc
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import t from './types'
import { transformTails } from './tails'
import { isa } from './is'
import { toStatement } from './blocks'

validateComprehensionLoopBody(loopBodyPath) ->
loopBodyPath.traverse({
import { getLoc, placeAtLoc as atLoc, placeAtNode as atNode, getSurroundingLoc, span } from 'ast-loc-utils'

validateComprehensionBody(path) ->
path.traverse({
noScope: true

Function(path): void -> path.skip()
Expand All @@ -20,46 +24,26 @@ validateComprehensionLoopBody(loopBodyPath) ->
throw returnPath.buildCodeFrameError("`return` is not allowed within Comprehensions.");
})

wrapComprehensionInIife(bodyVarId, bodyVarInitializer, loopBody) ->
t.callExpression(
t.arrowFunctionExpression(
[]
t.blockStatement([
t.variableDeclaration(
"const", [t.variableDeclarator(bodyVarId, bodyVarInitializer)]
)
loopBody
t.returnStatement(bodyVarId)
])
)
[]
)

export transformArrayComprehension(path) ->
validateComprehensionLoopBody(path.get("loop.body"))

id = path.scope.generateUidIdentifier("arr")
transformTails(
path.get("loop.body")
true
true
(expr) ->
t.callExpression(
t.memberExpression(id, t.identifier("push"))
[expr]
)
)
iife(body, id, initializer) ->
loc = body~getSurroundingLoc()

path.replaceWith(wrapComprehensionInIife(id, t.arrayExpression(), path.node.loop))
body.unshift(t.variableDeclaration("const",
[t.variableDeclarator(id, initializer)~atNode(id)]
)~atNode(id))
body.push(t.returnStatement(id)~atLoc(loc~span(-1)))

export transformObjectComprehension(path) ->
validateComprehensionLoopBody(path.get("loop.body"))
t.callExpression(
t.arrowFunctionExpression([], t.blockStatement(body)~atLoc(loc))~atLoc(loc)
[]
)~atLoc(loc)

const id = path.scope.generateUidIdentifier("obj")
retailObject(path, id, transformPathName, returnPathName) ->
transformPath = path.get(transformPathName)
validateComprehensionBody(transformPath)
transformTails(
path.get("loop.body")
true
transformPath
true
false
(seqExpr, tailPath) ->
if (
seqExpr.type !== "SequenceExpression" or
Expand All @@ -71,9 +55,107 @@ export transformObjectComprehension(path) ->
[ keyExpr, valExpr ] = seqExpr.expressions

t.assignmentExpression("=",
t.memberExpression(id, keyExpr, true),
t.memberExpression(id, keyExpr, true)~atNode(seqExpr),
valExpr
)
)~atNode(seqExpr)
)

path.replaceWith(wrapComprehensionInIife(id, t.objectExpression([]), path.node.loop))
path.get(returnPathName).node

retailArray(path, id, transformPathName, returnPathName) ->
transformPath = path.get(transformPathName)
validateComprehensionBody(transformPath)
transformTails(
transformPath
true
false
(expr) ->
t.callExpression(
t.memberExpression(id, t.identifier("push")~atNode(expr))~atNode(expr)
[expr]
)~atNode(expr)
)

path.get(returnPathName).node

transformLoop(path, ref, isObject, stmts) ->
if isObject:
stmts.push(retailObject(path, ref, "loop.body", "loop"))
else:
stmts.push(retailArray(path, ref, "loop.body", "loop"))

transformCase(path, ref, isObject, stmts) ->
if isObject:
stmts.push(retailObject(path, ref, "conditional", "conditional"))
else:
stmts.push(retailArray(path, ref, "conditional", "conditional"))

pushBundle(stmts, ref, bundle, isObject) ->
if isObject:
// _ref.k1 = v1; _ref.k2 = v2; ...
for elem property in bundle:
loc = property~getLoc()
stmts.push(
t.assignmentExpression("="
t.memberExpression(ref, property.key, property.computed)~atLoc(loc)
property.value
)~atLoc(loc)~toStatement()
)
else:
loc = getSurroundingLoc(bundle)
// _ref.push(bundle...)
stmts.push(
t.callExpression(
t.memberExpression(ref, t.identifier("push")~atLoc(loc))~atLoc(loc)
bundle
)~atLoc(loc)~toStatement()
)

export transformComprehension(path, isObject) ->
{ node } = path
elements = if isObject: node.properties else: node.elements
nodeKey = if isObject: "properties" else: "elements"
stmts = []
id = path.scope.generateUidIdentifier(isObject ? "obj" : "arr")~t.clone()~atLoc(getLoc(node)~span(1))

let i = 0, len = elements.length, bundle = [], first = true, initializer
while i < len:
element = elements[i]
if element~isa("Comprehension"):
if first:
now initializer = bundle
now first = false
else:
if bundle.length > 0: stmts~pushBundle(id, bundle, isObject)
now bundle = []

match element:
| ~isa("LoopComprehension"):
path.get(`${nodeKey}.${i}`)~transformLoop(id, isObject, stmts)
| ~isa("CaseComprehension"):
path.get(`${nodeKey}.${i}`)~transformCase(id, isObject, stmts)
| else: throw new Error("Invalid comprehension node (this is an internal error)")
else:
bundle.push(element)

i++

if bundle.length > 0: stmts~pushBundle(id, bundle, isObject)

initializerLoc = if initializer.length == 0:
getLoc(node)~span(1)
else:
getSurroundingLoc(initializer)

finalInitializer = if isObject:
t.objectExpression(initializer)~atLoc(initializerLoc)
else:
t.arrayExpression(initializer)~atLoc(initializerLoc)

path.replaceWith(stmts~iife(id, finalInitializer))

export transformArrayComprehension(path): void ->
transformComprehension(path, false)

export transformObjectComprehension(path): void ->
transformComprehension(path, true)
Loading

0 comments on commit b93a9e2

Please sign in to comment.