Skip to content

Commit

Permalink
Fix reduction inside conditions, and other subtle aliasing issues
Browse files Browse the repository at this point in the history
Fixes #1586
  • Loading branch information
edemaine committed Nov 11, 2024
1 parent 1ac4711 commit d9f35a3
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 10 deletions.
7 changes: 4 additions & 3 deletions source/parser/lib.civet
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
NormalCatchParameter
ParenthesizedExpression
Placeholder
StatementNode
StatementTuple
SwitchStatement
TypeArguments
Expand All @@ -46,7 +47,6 @@ import {
gatherRecursive
gatherRecursiveAll
gatherRecursiveWithinFunction
type Predicate
} from ./traversal.civet

import {
Expand Down Expand Up @@ -156,7 +156,7 @@ import {
getSync
} from ../parser.hera

function addPostfixStatement(statement: StatementTuple, ws: ASTNode, post)
function addPostfixStatement(statement: StatementNode, ws: ASTNode, post: IterationStatement | ForStatement | IfStatement)
expressions := [
...post.blockPrefix or []
["", statement]
Expand All @@ -166,9 +166,10 @@ function addPostfixStatement(statement: StatementTuple, ws: ASTNode, post)
type: "BlockStatement"
children: [" { ", expressions, " }"]
expressions
bare: false
}

children := [...post.children, block]
children := [ ...post.children, block ]

// This removes trailing whitespace for easier testing
if (!isWhitespaceOrEmpty(ws)) children.push(ws)
Expand Down
8 changes: 5 additions & 3 deletions source/parser/types.civet
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ export type OtherNode =
| Yield

export type IsToken = { token: string }
export type IsParent = { children: Children }
export type IsParent = { children: Children } & object
export type ASTNodeParent = ASTNodeObject & IsParent
export type Parent = (ASTNodeObject & IsParent)?
export type Children = ASTNode[] & (type?: undefined) & (token?: undefined)
export type ASTString = string & (type?: undefined) & (token?: undefined)
export type Children = ASTNode[] & (type?: undefined) & (token?: undefined) & (children?: undefined)
export type ASTString = string & (type?: undefined) & (token?: undefined) & (children?: undefined)

// Wrapper nodes are just for making non-object nodes into objects
// so that they have a parent, needed for e.g. `replaceNode`.
Expand Down Expand Up @@ -358,6 +358,7 @@ export type IterationStatement
block: BlockStatement
negated: boolean?
generator?: ASTNode
object?: boolean
resultsRef: ASTRef?

export type BreakStatement
Expand Down Expand Up @@ -403,6 +404,7 @@ export type ForStatement
generator?: ASTNode
resultsRef: ASTRef?
reduction?: ForReduction
object?: boolean

export type ForDeclaration
type: "ForDeclaration"
Expand Down
14 changes: 11 additions & 3 deletions source/parser/util.civet
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
ASTNode
ASTNodeObject
ASTNodeParent
Children
FunctionNode
IsParent
IsToken
Expand Down Expand Up @@ -245,16 +246,23 @@ function insertTrimmingSpace(target: ASTNode, c: string): ASTNode
if Array.isArray target
return c if target.length is 0

target.map (e, i) =>
for each e, i of target
if i is 0
insertTrimmingSpace(e, c)
else
e
else if isParent target
{
oldChildren := target.children
target = {
...target
children: insertTrimmingSpace(target.children, c)
children: insertTrimmingSpace target.children, c
}
// Preserve aliased properties
for key in target
i := oldChildren.indexOf target[key]
if i >= 0
target[key] = target.children[i]
target
else if isToken target
{
...target
Expand Down
2 changes: 1 addition & 1 deletion test/comptime.civet
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ describe "comptime", ->
---
x = comptime 1+2 else 0
---
x = (()=>{ return 0})()
x = (()=>{return 0})()
"""

testCase """
Expand Down
8 changes: 8 additions & 0 deletions test/for.civet
Original file line number Diff line number Diff line change
Expand Up @@ -1466,3 +1466,11 @@ describe "for", ->
results1 += item * item
};const nonNullSOS =results1
"""

testCase """
in postfix
---
return false unless for every f of facesHit
---
if (!(()=>{let results=true;for (const f of facesHit) {results = false; break}return results})()) { return false }
"""

0 comments on commit d9f35a3

Please sign in to comment.