Skip to content

Commit

Permalink
Merge pull request #1537 from DanielXMoore/rslice-amp
Browse files Browse the repository at this point in the history
Placeholders lift through reverse slice operators
  • Loading branch information
edemaine authored Oct 29, 2024
2 parents b7f3379 + b003f7c commit 5b817f5
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
9 changes: 7 additions & 2 deletions source/parser/lib.civet
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
ASTNodeParent
ASTRef
BlockStatement
Call
CallExpression
CaseBlock
CatchBinding
Expand Down Expand Up @@ -46,6 +47,7 @@ import {
gatherRecursive
gatherRecursiveAll
gatherRecursiveWithinFunction
type Predicate
} from ./traversal.civet

import {
Expand Down Expand Up @@ -663,6 +665,7 @@ function processCallMemberExpression(node: CallExpression | MemberExpression): A
return makeNode {...node,
children: [
type: "CallExpression" as const
implicit: true
children: [
getHelperRef "rslice"
makeNode {
Expand Down Expand Up @@ -1459,7 +1462,9 @@ function processPlaceholders(statements: StatementTuple[]): void
if exp.subtype is "."
// Partial placeholder . lifts to the nearest call expression,
// including the call itself and any surrounding unary operations.
{ ancestor } = findAncestor exp, .type is "Call"
{ ancestor } = findAncestor exp,
($): $ is Call => $.type is "Call" and
not ($.parent as CallExpression?)?.implicit
ancestor = ancestor?.parent
while ancestor?.parent? and ancestor.parent.type is like "UnaryExpression", "NewExpression", "AwaitExpression", "ThrowStatement", "StatementExpression"
ancestor = ancestor.parent
Expand All @@ -1477,7 +1482,7 @@ function processPlaceholders(statements: StatementTuple[]): void
if type is "IfStatement"
liftedIfs.add ancestor
(or)
type is "Call"
type is "Call" and not (ancestor.parent as CallExpression?)?.implicit
// Block, except for if/else blocks when condition already lifted
type is "BlockStatement" and
not (ancestor.parent is like {type: "IfStatement"} and liftedIfs.has ancestor.parent as IfStatement) and
Expand Down
8 changes: 8 additions & 0 deletions source/parser/types.civet
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type StatementNode =
*/
export type ExpressionNode =
| ArrayExpression
| AwaitExpression
| AssignmentExpression
| BinaryOp
| CallExpression
Expand Down Expand Up @@ -240,6 +241,7 @@ export type MemberExpression

export type CallExpression
type: "CallExpression"
implicit?: boolean // manufactured by Civet to implement an operator?
children: Children
parent?: Parent

Expand All @@ -261,6 +263,11 @@ export type Await
parent?: Parent
op?: ASTNode

export type AwaitExpression
type: "AwaitExpression"
children?: Children
parent?: Parent

export type NewExpression
type: "NewExpression"
children: Children
Expand Down Expand Up @@ -925,6 +932,7 @@ export type ReturnTypeAnnotation =
optional?: ASTNode
t: TypeNode
children: Children
parent?: Parent

export type MethodModifier =
get?: boolean
Expand Down
22 changes: 22 additions & 0 deletions test/function-block-shorthand.civet
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,28 @@ describe "&. function block shorthand", ->
x.map($ => $.slice(0, 2 + 1 || 1/0))
"""

testCase """
reverse slice
---
x.map &[..>=]
---
var modulo: (a: number, b: number) => number = (a, b) => (a % b + b) % b;
type RSliceable<R> = string | {length: number; slice(start: number, end: number): {reverse(): R}}
var rslice: <R, T extends string | RSliceable<R>>(a: T, start?: number, end?: number) => T extends string ? string : T extends RSliceable<infer R> ? R : never = ((a, start, end) => {
const l = a.length
start = modulo(start ?? -1, l)
end = modulo((end ?? -1) + 1, l)
if (typeof a === 'string') {
let r = ""
for (let i = start; i >= end; --i) r += a[i]
return r as any
} else {
return a.slice(end, start + 1).reverse()
}
});
x.map($ => rslice($, -1, 0 - 1))
"""

testCase """
kitchen sink
---
Expand Down

0 comments on commit 5b817f5

Please sign in to comment.