### Receiver Matching Example Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Demonstrates how to define receiver matching for cases where the call owner differs from the expected type, by using `Recv.union` to include multiple receiver types. ```scala private val seqRecv = Recv.union( "scala.collection.Seq", "scala.collection.SeqOps", // sortWith, sortBy "scala.collection.StrictOptimizedIterableOps", // flatten // ... ) ``` -------------------------------- ### Custom Compile-Time Errors for Port Parsing Source: https://github.com/kitlangton/neotype/blob/main/README.md Illustrates using `comptimeError` to provide descriptive compile-time errors for invalid input. This example parses a port number and fails compilation if it's out of the valid range (1-65535). ```scala inline def parsePort(inline s: String): Int = comptime { val port = s.toInt if port < 1 || port > 65535 then comptimeError(s"Invalid port: $port. Must be 1-65535") port } parsePort("8080") // ✓ Compiles to: 8080 parsePort("99999") // ✗ Compile error: Invalid port: 99999 ``` -------------------------------- ### Neotype Compile-Time Error Example Source: https://github.com/kitlangton/neotype/blob/main/README.md This example demonstrates the compilation error that occurs when a newtype's validation rule is violated. ```scala Error: /src/main/scala/examples/Main.scala:9:16 NonEmptyString("") ^^^^^^^^^^^^^^^^^^ —— Neotype Error —————————————————————————————————————————————————————————— NonEmptyString was called with an INVALID String. input: "" check: input.nonEmpty ——————————————————————————————————————————————————————————————————————————— ``` -------------------------------- ### Common Patterns for Adding New Stdlib Rules Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md Quick reference table for common patterns when adding new stdlib rules, including table types and helper functions. ```scala | Pattern | Table type | Helper | Use case | |---------|-----------|--------|----------| | `recv.op()` | `A => R` | `opsList` | Basic accessors (head, tail, reverse) | | `recv.op(arg)` | `(A, B) => R` | `ops1List[B]` | Single-arg ops (take, drop) | | `recv.op(a, b)` | `(A, B, C) => R` | `ops2IntIntList` | Two-arg ops (slice) | | `recv.op(f)` with `f: Any => Boolean` | `(A, F) => R` | `ops1PredList` | Predicate ops (exists, filter) | | `recv.op(f)` with `f: Any => Any` | `(A, F) => R` | `ops1FnList` | Transform ops (map, groupBy) | | `recv.op(f)` with `f: (Any,Any) => Boolean` | custom | `sortWithAny` | Binary predicates (sortWith) | | `recv.op(f)` with `f: (Any,Any) => Any` | custom | `reduceAny` | Binary ops (reduce, foldLeft) | | `recv.op()` with implicit | `A => R` | `anyArityOpsList` | Ops with implicits (sum, flatten) | ``` -------------------------------- ### Baseline Compile and Test Commands Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/PERF_PLAN.md Use these shell commands to establish a baseline performance measurement for the project's compilation and testing phases on the main branch. ```shell (time sbt "clean; comptimeJVM/compile") ``` ```shell (time sbt "clean; neotypeJVM/test") ``` -------------------------------- ### Static Assertions for Configuration Constants Source: https://github.com/kitlangton/neotype/blob/main/README.md Uses `comptime` and `staticAssert` to validate invariants between configuration constants at compile time. This catches bugs early by ensuring relationships between constants hold true. ```scala import comptime.* inline def staticAssert(inline cond: Boolean, inline msg: String): Unit = comptime { if !cond then comptimeError(msg) } object Config: inline val BUFFER_SIZE = 4096 inline val MAX_ITEMS = 100 inline val ITEM_SIZE = 40 // Catches bugs when ANY constant changes! staticAssert( BUFFER_SIZE >= MAX_ITEMS * ITEM_SIZE, "Buffer too small for max items" ) staticAssert( (BUFFER_SIZE & (BUFFER_SIZE - 1)) == 0, "Buffer size must be power of 2" ) ``` -------------------------------- ### Arity Matching for Implicits Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Explains the use of `anyArityOpsList` for methods with implicits, as Scala resolves implicits at compile time, potentially leading to varied arity appearances. It also covers curried methods with implicits using `ruleRecv1AnyArity`. ```scala # Methods with implicits (like `sum`, `sorted`, `flatten`) use `anyArityOpsList` because: # - Scala resolves implicits at compile time → arity appears as A0 # - But sometimes they show up as A1 or A1_1 # - `ASet(Set.empty)` matches any arity # For curried methods with implicits (like `sortBy(f)(implicit ord)`): # - Use `ruleRecv1AnyArity` which tries A1 first, then A1_1 # - Or skip and document as unsupported (complex cases) ``` -------------------------------- ### ZIO JSON Codec for NonEmptyString Source: https://github.com/kitlangton/neotype/blob/main/README.md Integrates Neotype's NonEmptyString with ZIO JSON by importing `given`. This automatically generates a `JsonCodec` for the newtype, supporting custom failure messages. Ensure the import is in the same file as the case class using the newtype. ```scala import neotype.interop.ziojson.given import zio.json.* case class Person(name: NonEmptyString, age: Int) derives JsonCodec val parsed = """{"name": "Kit", "age": 30}""".fromJson[Person] // Right(Person(NonEmptyString("Kit"), 30)) val failed = """{"name": "", "age": 30}""".fromJson[Person] // Left(".name(String must not be empty)") ``` -------------------------------- ### Compile-Time and Runtime SemVer Parsing Source: https://github.com/kitlangton/neotype/blob/main/README.md Demonstrates sharing parsing logic between compile-time and runtime using `inline def` and `comptime`. Compile-time parsing results in a compile error for invalid input, while runtime parsing returns an `Either` for graceful error handling. ```scala import comptime.* final case class SemVer(major: Int, minor: Int, patch: Int) object SemVer: // Shared parsing logic - inline so it works in both contexts private inline def doParse(s: String): Either[String, SemVer] = val parts = s.split("\\.").toList parts match case List(maj, min, pat) => Right(SemVer(maj.toInt, min.toInt, pat.toInt)) case _ => Left(s"Invalid semver: $s") // COMPILE-TIME: invalid input = compile error inline def parse(inline s: String): SemVer = comptime { doParse(s).fold(comptimeError(_), identity) } // RUNTIME: for user input, returns Either def parseEither(s: String): Either[String, SemVer] = doParse(s) // Compile-time - literal in bytecode val version = SemVer.parse("1.2.3") // → SemVer(1, 2, 3) // Runtime - graceful error handling SemVer.parseEither(userInput) match case Right(v) => println(s"Valid: $v") case Left(e) => println(s"Error: $e") ``` -------------------------------- ### Arity Matching for Curried Methods with Implicits Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md Demonstrates using `ruleRecv1AnyArity` for curried methods with implicits, which attempts A1 then A1_1. ```scala ruleRecv1AnyArity which tries A1 first, then A1_1 ``` -------------------------------- ### Add Neotype Dependency to Scala Project Source: https://github.com/kitlangton/neotype/blob/main/README.md Include these lines in your build.sbt to add Neotype and its optional comptime engine to your project. ```scala "io.github.kitlangton" %% "neotype" % "x.y.z" "io.github.kitlangton" %% "comptime" % "x.y.z" // optional ``` -------------------------------- ### Arity Matching for Implicits with `anyArityOpsList` Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md Explains the use of `anyArityOpsList` for methods with implicits, which can appear with different arities (A0, A1, A1_1). ```scala ASet(Set.empty) matches any arity ``` -------------------------------- ### Compile-Time Prime Number Calculation Source: https://github.com/kitlangton/neotype/blob/main/README.md Uses the `comptime` module to evaluate a list of prime numbers up to 50 at compile time. The result is inlined as a literal in the compiled code. ```scala import comptime.* val primes = comptime { (2 to 50).toList.filter(n => (2 until n).forall(n % _ != 0)) } // Compiles to: List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47) ``` -------------------------------- ### Lookup Ordering/Numeric via TypeClassMaps Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Use TypeClassMaps to dynamically retrieve Ordering or Numeric instances based on the runtime class of collection elements for operations like max and sum. ```scala // Look up Ordering/Numeric based on element's runtime class x.max(TypeClassMaps.getOrdering(xs.head, "max")) x.sum(TypeClassMaps.getNumeric(xs.head, "sum")) ``` -------------------------------- ### Add Debug Output for AST Inspection Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Use this to print the contents of 'targs' for debugging purposes. Observe common patterns like empty lists or specific type references. ```scala println(s"[DEBUG] targs=${call.targs}") ``` -------------------------------- ### Adding Exception Constructors for Catching Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md To support catching new exception types, add their constructors to TermCompiler.exceptionConstructors. This allows reconstruction of exceptions thrown during rule evaluation. ```scala // Example: Adding constructor for NoSuchElementException // TermCompiler.exceptionConstructors += "NoSuchElementException" -> ( (args: Seq[Any]) => new java.util.NoSuchElementException(args.head.asInstanceOf[String]) ) ``` -------------------------------- ### Testing Try/Catch with Naturally Occurring Exceptions Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md When testing try/catch blocks, use exceptions that occur naturally during evaluation (e.g., ArithmeticException from division by zero) as exception constructors are not supported. ```scala // "abc".toInt → NumberFormatException // List(1)(10) → IndexOutOfBoundsException // 1 / 0 → ArithmeticException // "abc".charAt(10) → StringIndexOutOfBoundsException ``` -------------------------------- ### Testing Try/Catch with Naturally-Occurring Exceptions Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md Exception constructors like `new RuntimeException(...)` are not supported for testing try/catch blocks. Use naturally-occurring exceptions such as NumberFormatException, IndexOutOfBoundsException, ArithmeticException, or StringIndexOutOfBoundsException. ```scala // Examples of naturally-occurring exceptions for testing: // "abc".toInt -> NumberFormatException // List(1)(10) -> IndexOutOfBoundsException // 1 / 0 -> ArithmeticException // "abc".charAt(10) -> StringIndexOutOfBoundsException ``` -------------------------------- ### Mapping Scala Package Aliases for Exceptions Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Map Scala package-aliased exception types to their corresponding Java classes in PatternNames.scalaPackageAliases to enable correct pattern matching in try/catch blocks. ```scala // Example: Mapping scala.package$.NumberFormatException to java.lang.NumberFormatException ``` -------------------------------- ### S/L Pattern for Lazy Arguments Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Illustrates the S/L (Strict/Lazy) suffix pattern used to describe argument positions for by-name arguments in methods. This pattern helps clarify evaluation order. ```scala byName_L # 1 arg, lazy byName_SL # 2 args: strict, then lazy (e.g., getOrElse) byName_LS # 2 args: lazy, then strict (e.g., fold) byName_SLL # 3 args: strict, then 2 lazy ``` ```scala byName1_1_LS # curried (1)(1), lazy first, strict second byName1_1_SL # curried (1)(1), strict first, lazy second ``` -------------------------------- ### Define NonEmptyString Newtype Source: https://github.com/kitlangton/neotype/blob/main/README.md Defines a NonEmptyString newtype with validation to ensure strings are not empty. This is a prerequisite for ZIO JSON integration. ```scala import neotype.* type NonEmptyString = NonEmptyString.Type object NonEmptyString extends Newtype[String]: override inline def validate(value: String): Boolean | String = if value.nonEmpty then true else "String must not be empty" ``` -------------------------------- ### Reconstructing Exceptions with TermCompiler Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Add constructors to TermCompiler.exceptionConstructors to enable the reconstruction of real exceptions from EvalExceptions, facilitating try/catch functionality for custom exception types. ```scala // Add constructor for a new exception type ``` -------------------------------- ### Mapping Scala Package Aliases for Exceptions Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/AGENTS.md Exception types in catch patterns require mapping to Java classes in PatternNames.scalaPackageAliases for correct pattern matching. Ensure both scala.package$.ExceptionName and scala.ExceptionName variants are added. ```scala // Example: Mapping NumberFormatException // scala.package.NumberFormatException -> java.lang.NumberFormatException ``` -------------------------------- ### Distinguishing StringOps.map Overloads using Call.targs Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Check call.targs.isEmpty to differentiate between the Char => Char overload (empty targs) and the generic [B] overload (non-empty targs) of StringOps.map. ```scala RuleDsl.rule("map") .recv(stringOpsRecv) .a1 .compile("StringOps.map") { (call, ctx) => for recvEval <- ctx.compileTerm(call.recv) argEval <- ctx.compileTerm(call.args.head.head) yield // Empty targs = Char => Char overload, non-empty = generic [B] overload val returnsString = call.targs.isEmpty Eval.Apply2(recvEval, argEval, Eval.Value(returnsString), (recv, fn, isStringResult) => val s = recv.asInstanceOf[String] val f = fn.asInstanceOf[Char => Any] if isStringResult.asInstanceOf[Boolean] then s.map(c => f(c).asInstanceOf[Char]) // String result else s.map(f) // IndexedSeq result ) } ``` -------------------------------- ### Define TypeIR Structure Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Defines the TypeIR sealed trait and its companion object with case classes for Ref and AnyType. Use this structure to represent types within the system. ```scala sealed trait TypeIR object TypeIR: case class Ref(fullName: String, args: List[TypeIR]) // e.g., Ref("scala.Int", Nil) case class AnyType() // unknown/erased type ``` -------------------------------- ### Validated Strings with Neotype in Scala Source: https://github.com/kitlangton/neotype/blob/main/README.md Create newtypes for strings with validation rules such as minimum length and character set restrictions. ```scala type Username = Username.Type object Username extends Newtype[String]: override inline def validate(value: String) = if value.length < 3 then "Username must be at least 3 characters" else if !value.forall(_.isLetterOrDigit) then "Username must be alphanumeric" else true ``` -------------------------------- ### Arity Constants Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Defines constants for representing flat and curried argument counts (arities) using underscores to separate curried argument counts. ```scala A0, A1, A2, A3 # flat arities A1_1, A1_2, A2_1 # curried: A1_1 = (1 arg)(1 arg) ``` -------------------------------- ### Check if a Type is CharType Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Implement type checking for CharType using pattern matching on the TypeIR structure. This function returns true if the given TypeIR represents a Char. ```scala def isCharType(tpe: TypeIR): Boolean = tpe match case TypeIR.Ref(name, _) => name == "scala.Char" || name == "Char" case _ => false ``` -------------------------------- ### Type-Safe IDs with Neotype in Scala Source: https://github.com/kitlangton/neotype/blob/main/README.md Create distinct types for IDs (e.g., UserId, OrderId) using Neotype to prevent accidental mixing of different ID types. ```scala import neotype.* // Type-safe IDs - prevent mixing up different entity types type UserId = UserId.Type object UserId extends Newtype[Long] type OrderId = OrderId.Type object OrderId extends Newtype[Long] def getUser(id: UserId): User = ... def getOrder(id: OrderId): Order = ... getUser(UserId(123)) // ✓ Compiles getUser(OrderId(456)) // ✗ Won't compile - type mismatch! ``` -------------------------------- ### Handling Type Erasure with Call.targs in Rules Source: https://github.com/kitlangton/neotype/blob/main/modules/comptime/CLAUDE.md Use call.targs (List[TypeIR]) within rules to access compile-time type information preserved from the AST, which is crucial when runtime inspection fails due to type erasure. ```scala // Erased to handle both Char => Char and Char => Int val mapRule: (String, Char => Any) => Any = ... ``` -------------------------------- ### Bounded Numbers with Neotype Validation in Scala Source: https://github.com/kitlangton/neotype/blob/main/README.md Define a newtype for numbers with specific range constraints. The validation message provides details on the violation. ```scala type Port = Port.Type object Port extends Newtype[Int]: override inline def validate(value: Int) = if value >= 1 && value <= 65535 then true else s"Port must be 1-65535, got: $value" Port(8080) // ✓ Compiles Port(99999) // ✗ Compile error: Port must be 1-65535 ``` -------------------------------- ### Geographic Coordinates Validation with Neotype in Scala Source: https://github.com/kitlangton/neotype/blob/main/README.md Define a newtype for geographic coordinates (e.g., Latitude) with validation to ensure values fall within the correct range. ```scala type Latitude = Latitude.Type object Latitude extends Newtype[Double]: override inline def validate(value: Double) = if value >= -90 && value <= 90 then true else s"Latitude must be -90 to 90, got: $value" ``` -------------------------------- ### Define a Compile-Time Validated Newtype in Scala Source: https://github.com/kitlangton/neotype/blob/main/README.md Define a newtype with a validation rule that is checked at compile time. The `validate` method returns a Boolean indicating validity. ```scala import neotype.* // 1. Define a newtype. object NonEmptyString extends Newtype[String]: // 2. Optionally, define a validate method. override inline def validate(input: String): Boolean = input.nonEmpty // 3. Construct values. NonEmptyString("Hello") // OK NonEmptyString("") // Compile Error ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.