Skip to content
Merged
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
38 changes: 38 additions & 0 deletions tools/res-to-affine/test/fixtures/partial1.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MPL-2.0
// #488 partial-port fixture: module-top-level functions -> `fn` skeletons
// with switch->match, pipe desugaring, if/else, blocks, array/record literals,
// and best-effort expression translation. Output is NOT expected to
// type-check; it must parse, with un-translatable forms (e.g. an
// interpolated template string) as TODO holes.

let classify = x => switch x {
| Some(n) => n + 1
| None => 0
}

let area = (w, h) => w *. h

let greet = name => "hi " ++ name

let log2 = msg => Js.log(msg)

// pipe-first desugars: x->doStuff(1) -> doStuff(x, 1)
let piped = x => x->doStuff(1)

// pipe chain desugars left-to-right: x->f->g(2) -> g(f(x), 2)
let chain = x => x->f->g(2)

// if/else
let clamp = x => if x > 0 { x } else { 0 }

// block with a let statement
let scaled = x => { let y = x + 1; y * 2 }

// array literal -> [x, x]
let pair = x => [x, x]

// record literal -> Rec #{ x: x, y: y } (nominal placeholder type)
let mkpt = (x, y) => {x: x, y: y}

// interpolated template string has no handler yet -> must become a TODO hole.
let tmpl = x => `val=${x}`
83 changes: 83 additions & 0 deletions tools/res-to-affine/test/fixtures/phase2c.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: MPL-2.0
// Synthetic fixture for the two anti-patterns that were explicitly
// deferred from Phase 1 entirely because they need real AST:
// 1. inline-callback-record — 3+ inline function values in a single
// record literal or a single call's labelled-argument list
// 2. oversized-function — function spans more than 50 source rows
// Walker-only by construction; the line-regex scanner does not detect
// either pattern.

open Types

// --- inline-callback-record: a record literal with 4 inline lambdas
let handlers = {
onMount: () => Js.log("mounted"),
onUnmount: () => Js.log("unmounted"),
onClick: e => Js.log(e),
onHover: e => Js.log(e),
}

// --- inline-callback-record at a call site: 3 labelled-argument lambdas
let _ = Widget.make(
~onMount=() => Js.log("mounted"),
~onUnmount=() => Js.log("unmounted"),
~onClick=e => Js.log(e),
)

// --- oversized-function: 60 source-row span. Body intentionally tedious
// to surface the row-span proxy the walker uses.
let huge = id => {
let a01 = id + 1
let a02 = a01 + 1
let a03 = a02 + 1
let a04 = a03 + 1
let a05 = a04 + 1
let a06 = a05 + 1
let a07 = a06 + 1
let a08 = a07 + 1
let a09 = a08 + 1
let a10 = a09 + 1
let a11 = a10 + 1
let a12 = a11 + 1
let a13 = a12 + 1
let a14 = a13 + 1
let a15 = a14 + 1
let a16 = a15 + 1
let a17 = a16 + 1
let a18 = a17 + 1
let a19 = a18 + 1
let a20 = a19 + 1
let a21 = a20 + 1
let a22 = a21 + 1
let a23 = a22 + 1
let a24 = a23 + 1
let a25 = a24 + 1
let a26 = a25 + 1
let a27 = a26 + 1
let a28 = a27 + 1
let a29 = a28 + 1
let a30 = a29 + 1
let a31 = a30 + 1
let a32 = a31 + 1
let a33 = a32 + 1
let a34 = a33 + 1
let a35 = a34 + 1
let a36 = a35 + 1
let a37 = a36 + 1
let a38 = a37 + 1
let a39 = a38 + 1
let a40 = a39 + 1
let a41 = a40 + 1
let a42 = a41 + 1
let a43 = a42 + 1
let a44 = a43 + 1
let a45 = a44 + 1
let a46 = a45 + 1
let a47 = a46 + 1
let a48 = a47 + 1
let a49 = a48 + 1
let a50 = a49 + 1
let a51 = a50 + 1
let a52 = a51 + 1
a52
}
36 changes: 36 additions & 0 deletions tools/res-to-affine/test/fixtures/phase3.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MPL-2.0
// Synthetic fixture for Phase 3 slice 1: structural type-declaration
// translation. The first three type declarations are fully structural
// and #228-independent, so the walker's --translate path renders them
// as compilable AffineScript:
// type userId = int -> type UserId = Int
// type color = Red | ... -> type Color = | Red | Green | Blue
// type shape = Circle(...) -> type Shape = | Circle(Float) | Rect(Int, Int)
// The trailing `let`/`switch` is NOT a type declaration and stays a TODO
// island (absent from the translation list). The generic `box` below now
// translates too (slice 2: type parameters); the qualified-path decl stays
// skipped (qualified-path RHS is deferred — it would parse but not resolve).

type userId = int

type color =
| Red
| Green
| Blue

type shape =
| Circle(float)
| Rect(int, int)

// Slice 2: type parameters now translate -> type Box[A] = | Box(A)
type box<'a> = Box('a)

// Skipped: qualified-path RHS (deferred).
type theirMap = Belt.Map.t

// Not a type declaration: stays a TODO island.
let area = s =>
switch s {
| Circle(r) => r *. r
| Rect(w, h) => float_of_int(w * h)
}
28 changes: 28 additions & 0 deletions tools/res-to-affine/test/fixtures/phase3b.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MPL-2.0
// Phase 3 slice 2 fixture: record types (-> struct) and generics.
// type point = {x: int, y: int} -> struct Point { x: Int, y: Int }
// type box<'a> = {value: 'a} -> struct Box[A] { value: A }
// type id<'a> = 'a -> type Id[A] = A
// Records with `mutable` or optional `?` fields are SKIPPED (their
// semantics can't be dropped).

type point = {
x: int,
y: int,
}

type box<'a> = {
value: 'a,
}

type id<'a> = 'a

// SKIPPED: mutable field — AffineScript struct fields can't carry it.
type counter = {
mutable count: int,
}

// SKIPPED: optional field — `?` has no struct equivalent.
type config = {
verbose?: bool,
}
27 changes: 27 additions & 0 deletions tools/res-to-affine/test/fixtures/phase3c.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MPL-2.0
// Phase 3 slice 3 fixture: module-level `let <id> = <literal>` -> `const`.
// let answer = 42 -> const answer: Int = 42;
// let pi = 3.14 -> const pi: Float = 3.14;
// let greeting = "hi" -> const greeting: String = "hi";
// let enabled = true -> const enabled: Bool = true;
// Non-literal / ref / destructuring bindings are SKIPPED (not compile-time
// constants, or not a plain identifier).

let answer = 42

let pi = 3.14

let greeting = "hi"

let enabled = true

let disabled = false

// SKIPPED: non-literal body (a call) — not a compile-time constant.
let now = Date.now()

// SKIPPED: ref body is the mutable-global anti-pattern, not a const.
let counter = ref(0)

// SKIPPED: destructuring pattern, not a plain identifier.
let (a, b) = (1, 2)
Loading