diff --git a/.gitignore b/.gitignore index 0c2c2869..5a004f89 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,4 @@ testrun.log /Examples/AuditLogDemo/AuditLogDemo /Examples/WebSocketDemo/WebSocketDemo /Examples/StateMachine/StateMachine +core diff --git a/Book/AROByExample/AppendixA-CompleteCode.md b/Book/AROByExample/AppendixA-CompleteCode.md index 303ecf8b..18d0f910 100644 --- a/Book/AROByExample/AppendixA-CompleteCode.md +++ b/Book/AROByExample/AppendixA-CompleteCode.md @@ -16,27 +16,27 @@ The application entry point. Reads the starting URL and kicks off the crawl. ============================================================ *) (Application-Start: Web Crawler) { - "Starting Web Crawler..." to the . + Log "Starting Web Crawler..." to the . (* Read starting URL from environment *) - the from the . + Extract the from the . - "Starting URL: ${}" to the . + Log "Starting URL: ${}" to the . (* Create output directory *) - the with "./output". - the to the . - "Output directory created" to the . + Create the with "./output". + Make the to the . + Log "Output directory created" to the . (* Queue initial URL - Emit blocks until the entire crawl chain completes *) - a with { url: , base: }. + Emit a with { url: , base: }. - an for the . + Return an for the . } (Application-End: Success) { - "🥁 Web Crawler completed!" to the . - an for the . + Log "🥁 Web Crawler completed!" to the . + Return an for the . } ``` @@ -56,27 +56,27 @@ The core crawling logic. Fetches pages and triggers downstream processing. (Crawl Page: CrawlPage Handler) { (* Extract from event data *) - the from the . - the from the . - the from the . + Extract the from the . + Extract the from the . + Extract the from the . - "Crawling: ${}" to the . + Log "Crawling: ${}" to the . (* Fetch the page *) - the from the . + Request the from the . (* Extract markdown content from HTML using ParseHtml action *) - the from the . - the from the <markdown-result: title>. - <Extract> the <markdown-content> from the <markdown-result: markdown>. + ParseHtml the <markdown-result: markdown> from the <html>. + Extract the <title> from the <markdown-result: title>. + Extract the <markdown-content> from the <markdown-result: markdown>. (* Save the markdown content to file *) - <Emit> a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. + Emit a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. (* Extract links from the HTML *) - <Emit> a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. + Emit a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. - <Return> an <OK: status> for the <crawl>. + Return an <OK: status> for the <crawl>. } ``` @@ -95,102 +95,102 @@ Link extraction, normalization, filtering, and queuing. (Extract Links: ExtractLinks Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Use ParseHtml action to extract all href attributes from anchor tags *) - <ParseHtml> the <links: links> from the <html>. + ParseHtml the <links: links> from the <html>. (* Process links in parallel - repository Actor ensures atomic dedup *) parallel for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { + Emit a <NormalizeUrl: event> with { raw: <raw-url>, source: <source-url>, base: <base-domain> }. } - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } (Normalize URL: NormalizeUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <raw-url> from the <event-data: raw>. - <Extract> the <source-url> from the <event-data: source>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <raw-url> from the <event-data: raw>. + Extract the <source-url> from the <event-data: source>. + Extract the <base-domain> from the <event-data: base>. (* Determine URL type and normalize *) match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^\/$/ { (* Just "/" means root - use base domain as-is (no trailing slash) *) - <Emit> a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. + Emit a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. } case /^\// { (* Root-relative URL: prepend base domain, strip fragment and trailing slash *) - <Create> the <joined-url> with "${<base-domain>}${<raw-url>}". - <Split> the <frag-parts> from the <joined-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Create the <joined-url> with "${<base-domain>}${<raw-url>}". + Split the <frag-parts> from the <joined-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^(#|mailto:|javascript:|tel:|data:)/ { (* Skip fragments and special URLs *) } } - <Return> an <OK: status> for the <normalization>. + Return an <OK: status> for the <normalization>. } (Filter URL: FilterUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Filter URLs that belong to the same domain as base-domain *) - <Emit> a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. + Emit a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. - <Return> an <OK: status> for the <filter>. + Return an <OK: status> for the <filter>. } (Queue URL: QueueUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Generate deterministic id from URL hash for deduplication *) - <Compute> the <url-id: hash> from the <url>. + Compute the <url-id: hash> from the <url>. (* Store with id - repository deduplicates by id, observer only fires for new entries *) - <Create> the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. - <Store> the <crawl-request> into the <crawled-repository>. + Create the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. + Store the <crawl-request> into the <crawled-repository>. - <Return> an <OK: status> for the <queue>. + Return an <OK: status> for the <queue>. } (Trigger Crawl: crawled-repository Observer) { (* React to new entries in the repository *) - <Extract> the <crawl-request> from the <event: newValue>. - <Extract> the <url> from the <crawl-request: url>. - <Extract> the <base-domain> from the <crawl-request: base>. + Extract the <crawl-request> from the <event: newValue>. + Extract the <url> from the <crawl-request: url>. + Extract the <base-domain> from the <crawl-request: base>. - <Log> "Queued: ${<url>}" to the <console>. - <Emit> a <CrawlPage: event> with { url: <url>, base: <base-domain> }. + Log "Queued: ${<url>}" to the <console>. + Emit a <CrawlPage: event> with { url: <url>, base: <base-domain> }. - <Return> an <OK: status> for the <observer>. + Return an <OK: status> for the <observer>. } ``` @@ -212,20 +212,20 @@ File storage handler. (Save Page: SavePage Handler) { (* Extract event data *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <title> from the <event-data: title>. - <Extract> the <content> from the <event-data: content>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <title> from the <event-data: title>. + Extract the <content> from the <event-data: content>. (* Generate a hash of the URL for the filename. Hashes are unique and filesystem-safe. The actual URL is preserved in the file content. *) - <Compute> the <url-hash: hash> from the <url>. + Compute the <url-hash: hash> from the <url>. (* Build the file path with string interpolation *) - <Create> the <file-path> with "./output/${<url-hash>}.md". + Create the <file-path> with "./output/${<url-hash>}.md". - <Log> "Saving: ${<url>} to ${<file-path>}" to the <console>. + Log "Saving: ${<url>} to ${<file-path>}" to the <console>. (* Format the Markdown file with metadata. \n creates newlines. @@ -234,13 +234,13 @@ File storage handler. - Source URL for reference - Separator - Actual content *) - <Create> the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". + Create the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". (* Write the content to the file. The 'file:' specifier indicates the target is a file path. *) - <Write> the <file-content> to the <file: file-path>. + Write the <file-content> to the <file: file-path>. - <Return> an <OK: status> for the <save>. + Return an <OK: status> for the <save>. } ``` diff --git a/Book/AROByExample/AppendixB-ActionQuickReference.md b/Book/AROByExample/AppendixB-ActionQuickReference.md index 7ce62b89..ca4c81f4 100644 --- a/Book/AROByExample/AppendixB-ActionQuickReference.md +++ b/Book/AROByExample/AppendixB-ActionQuickReference.md @@ -10,13 +10,13 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Extract | `<Extract> the <result> from the <source: field>.` | Extract a value from an object or specifier | +| Extract | `Extract the <result> from the <source: field>.` | Extract a value from an object or specifier | **Examples:** ```aro -<Extract> the <url> from the <event-data: url>. -<Extract> the <start-url> from the <env: CRAWL_URL>. -<Extract> the <title> from the <markdown-result: title>. +Extract the <url> from the <event-data: url>. +Extract the <start-url> from the <env: CRAWL_URL>. +Extract the <title> from the <markdown-result: title>. ``` --- @@ -25,12 +25,12 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Create | `<Create> the <result> with <value>.` | Create a new value | +| Create | `Create the <result> with <value>.` | Create a new value | **Examples:** ```aro -<Create> the <output-path> with "./output". -<Create> the <absolute-url> with "${<base>}${<path>}". +Create the <output-path> with "./output". +Create the <absolute-url> with "${<base>}${<path>}". ``` --- @@ -39,18 +39,18 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Compute | `<Compute> the <result: operation> from <input>.` | Perform a calculation | -| Compute | `<Compute> the <result: operation> from <a> with <b>.` | Perform a binary operation | +| Compute | `Compute the <result: operation> from <input>.` | Perform a calculation | +| Compute | `Compute the <result: operation> from <a> with <b>.` | Perform a binary operation | **Operations:** | Operation | Description | Example | |-----------|-------------|---------| -| length | String or list length | `<Compute> the <len: length> from <text>.` | -| count | Count items in list | `<Compute> the <count: count> from <list>.` | -| hash | Compute hash value | `<Compute> the <hash: hash> from <url>.` | -| union | Combine two lists (set union) | `<Compute> the <all: union> from <a> with <b>.` | -| difference | Items in first but not second | `<Compute> the <new: difference> from <a> with <b>.` | +| length | String or list length | `Compute the <len: length> from <text>.` | +| count | Count items in list | `Compute the <count: count> from <list>.` | +| hash | Compute hash value | `Compute the <hash: hash> from <url>.` | +| union | Combine two lists (set union) | `Compute the <all: union> from <a> with <b>.` | +| difference | Items in first but not second | `Compute the <new: difference> from <a> with <b>.` | --- @@ -58,11 +58,11 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Request | `<Request> the <result> from the <url>.` | HTTP GET request | +| Request | `Request the <result> from the <url>.` | HTTP GET request | **Example:** ```aro -<Request> the <html> from the <url>. +Request the <html> from the <url>. ``` --- @@ -71,15 +71,15 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| ParseHtml | `<ParseHtml> the <result: specifier> from the <html>.` | Parse HTML content | +| ParseHtml | `ParseHtml the <result: specifier> from the <html>.` | Parse HTML content | **Specifiers:** | Specifier | Returns | Example | |-----------|---------|---------| -| markdown | Object with title and markdown | `<ParseHtml> the <result: markdown> from <html>.` | -| links | List of href values | `<ParseHtml> the <links: links> from <html>.` | -| title | Page title string | `<ParseHtml> the <title: title> from <html>.` | +| markdown | Object with title and markdown | `ParseHtml the <result: markdown> from <html>.` | +| links | List of href values | `ParseHtml the <links: links> from <html>.` | +| title | Page title string | `ParseHtml the <title: title> from <html>.` | --- @@ -87,17 +87,17 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Split | `<Split> the <result> from the <string> by /regex/.` | Split string by regex pattern | +| Split | `Split the <result> from the <string> by /regex/.` | Split string by regex pattern | **Examples:** ```aro (* Split by fragment hash to strip URL fragments *) -<Split> the <parts> from the <url> by /#/. -<Extract> the <clean: first> from the <parts>. +Split the <parts> from the <url> by /#/. +Extract the <clean: first> from the <parts>. (* Split by trailing slashes to normalize URLs *) -<Split> the <parts> from the <url> by /\/+$/. -<Extract> the <clean: first> from the <parts>. +Split the <parts> from the <url> by /\/+$/. +Extract the <clean: first> from the <parts>. ``` --- @@ -106,13 +106,13 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Make | `<Make> the <result> to the <directory: path>.` | Create a directory | -| Write | `<Write> the <content> to the <file: path>.` | Write content to a file | +| Make | `Make the <result> to the <directory: path>.` | Create a directory | +| Write | `Write the <content> to the <file: path>.` | Write content to a file | **Examples:** ```aro -<Make> the <output-dir> to the <directory: output-path>. -<Write> the <file-content> to the <file: file-path>. +Make the <output-dir> to the <directory: output-path>. +Write the <file-content> to the <file: file-path>. ``` --- @@ -121,13 +121,13 @@ This appendix provides a quick reference for all actions used in the web crawler | Action | Syntax | Description | |--------|--------|-------------| -| Store | `<Store> the <value> into the <repository-name>.` | Save data to repository | -| Retrieve | `<Retrieve> the <result> from the <repository-name>.` | Load data from repository | +| Store | `Store the <value> into the <repository-name>.` | Save data to repository | +| Retrieve | `Retrieve the <result> from the <repository-name>.` | Load data from repository | **Examples:** ```aro -<Store> the <crawled-urls> into the <crawled-repository>. -<Retrieve> the <crawled-urls> from the <crawled-repository>. +Store the <crawled-urls> into the <crawled-repository>. +Retrieve the <crawled-urls> from the <crawled-repository>. ``` When storing plain values (not collections), `<Store>` also binds `new-entry` to the execution context: @@ -136,8 +136,8 @@ When storing plain values (not collections), `<Store>` also binds `new-entry` to This enables atomic deduplication: ```aro -<Store> the <url> into the <crawled-repository>. -<Emit> a <CrawlPage: event> with { url: <url> } when <new-entry> > 0. +Store the <url> into the <crawled-repository>. +Emit a <CrawlPage: event> with { url: <url> } when <new-entry> > 0. ``` --- @@ -146,11 +146,11 @@ This enables atomic deduplication: | Action | Syntax | Description | |--------|--------|-------------| -| Emit | `<Emit> a <EventType: event> with { ... }.` | Emit an event | +| Emit | `Emit a <EventType: event> with { ... }.` | Emit an event | **Example:** ```aro -<Emit> a <CrawlPage: event> with { url: <url>, base: <domain> }. +Emit a <CrawlPage: event> with { url: <url>, base: <domain> }. ``` --- @@ -159,12 +159,12 @@ This enables atomic deduplication: | Action | Syntax | Description | |--------|--------|-------------| -| Log | `<Log> "message" to the <console>.` | Write to console | +| Log | `Log "message" to the <console>.` | Write to console | **Examples:** ```aro -<Log> "Starting..." to the <console>. -<Log> "URL: ${<url>}" to the <console>. +Log "Starting..." to the <console>. +Log "URL: ${<url>}" to the <console>. ``` --- @@ -173,8 +173,8 @@ This enables atomic deduplication: | Action | Syntax | Description | |--------|--------|-------------| -| Keepalive | `<Keepalive> the <application> for the <events>.` | Keep app running for external events (servers only) | -| Return | `<Return> an <OK: status> for the <context>.` | Return success | +| Keepalive | `Keepalive the <application> for the <events>.` | Keep app running for external events (servers only) | +| Return | `Return an <OK: status> for the <context>.` | Return success | **Note:** Batch applications do not need `<Keepalive>` because `<Emit>` blocks until all downstream handlers complete. Only use `<Keepalive>` for applications that must stay alive to receive external events (e.g., HTTP servers, file watchers). @@ -185,7 +185,7 @@ This enables atomic deduplication: Actions can include `when` guards: ```aro -<Action> ... when <condition>. +Action ... when <condition>. ``` **Condition Types:** @@ -266,7 +266,7 @@ Escape sequences: ```aro (Feature Name: Business Activity) { (* statements *) - <Return> an <OK: status> for the <context>. + Return an <OK: status> for the <context>. } ``` @@ -288,39 +288,39 @@ Escape sequences: (Feature Name: Business Activity) { (* Extraction *) - <Extract> the <result> from the <source: field>. + Extract the <result> from the <source: field>. (* Creation *) - <Create> the <result> with <value>. + Create the <result> with <value>. (* Computation *) - <Compute> the <result: operation> from <input>. + Compute the <result: operation> from <input>. (* HTTP *) - <Request> the <result> from the <url>. + Request the <result> from the <url>. (* HTML parsing *) - <ParseHtml> the <result: specifier> from the <html>. + ParseHtml the <result: specifier> from the <html>. (* String splitting *) - <Split> the <parts> from the <string> by /regex/. + Split the <parts> from the <string> by /regex/. (* File I/O *) - <Make> the <dir> to the <directory: path>. - <Write> the <content> to the <file: path>. + Make the <dir> to the <directory: path>. + Write the <content> to the <file: path>. (* Repository *) - <Store> the <value> into the <repo>. - <Retrieve> the <value> from the <repo>. + Store the <value> into the <repo>. + Retrieve the <value> from the <repo>. (* Events *) - <Emit> a <Event: event> with { key: <value> }. + Emit a <Event: event> with { key: <value> }. (* Logging *) - <Log> "message ${<var>}" to the <console>. + Log "message ${<var>}" to the <console>. (* Conditional *) - <Action> ... when <condition>. + Action ... when <condition>. (* Control flow *) match <value> { @@ -331,6 +331,6 @@ Escape sequences: parallel for each <item> in <list> { ... } (* Return *) - <Return> an <OK: status> for the <context>. + Return an <OK: status> for the <context>. } ``` diff --git a/Book/AROByExample/Chapter01-Introduction.md b/Book/AROByExample/Chapter01-Introduction.md index 5495bb94..207caf64 100644 --- a/Book/AROByExample/Chapter01-Introduction.md +++ b/Book/AROByExample/Chapter01-Introduction.md @@ -21,7 +21,7 @@ ARO is a domain-specific language for expressing business logic as natural langu Here is your first ARO statement: ```aro -<Log> "Hello, World!" to the <console>. +Log "Hello, World!" to the <console>. ``` This reads naturally: "Log 'Hello, World!' to the console." The angle brackets mark the key elements: `<Log>` is the action, `"Hello, World!"` is what we're logging, and `<console>` is where we're sending it. @@ -35,7 +35,7 @@ This reads naturally: "Log 'Hello, World!' to the console." The angle brackets m Every ARO statement follows a consistent pattern: ``` -<Action> the <result> preposition the <object>. +Action the <result> preposition the <object>. ``` The components are: @@ -48,7 +48,7 @@ The components are: For example: ```aro -<Extract> the <username> from the <request: body>. +Extract the <username> from the <request: body>. ``` This extracts a value called `username` from the request body. The result `username` is now available for use in subsequent statements. diff --git a/Book/AROByExample/Chapter02-ProjectSetup.md b/Book/AROByExample/Chapter02-ProjectSetup.md index 1d12019d..c2441244 100644 --- a/Book/AROByExample/Chapter02-ProjectSetup.md +++ b/Book/AROByExample/Chapter02-ProjectSetup.md @@ -124,8 +124,8 @@ Let us add a minimal program to verify everything works. Open `main.aro` and add ```aro (Application-Start: Web Crawler) { - <Log> "Hello from ARO!" to the <console>. - <Return> an <OK: status> for the <startup>. + Log "Hello from ARO!" to the <console>. + Return an <OK: status> for the <startup>. } ``` diff --git a/Book/AROByExample/Chapter03-TheEntryPoint.md b/Book/AROByExample/Chapter03-TheEntryPoint.md index 8dcb033e..94e89210 100644 --- a/Book/AROByExample/Chapter03-TheEntryPoint.md +++ b/Book/AROByExample/Chapter03-TheEntryPoint.md @@ -24,7 +24,7 @@ The basic structure is: ```aro (Application-Start: Application Name) { (* Initialization statements *) - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -50,8 +50,8 @@ Let us build `main.aro` step by step. ```aro (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. - <Return> an <OK: status> for the <startup>. + Log "Starting Web Crawler..." to the <console>. + Return an <OK: status> for the <startup>. } ``` @@ -61,13 +61,13 @@ This logs a startup message and exits. Run it with `aro run .` to verify it work ```aro (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. + Log "Starting Web Crawler..." to the <console>. (* Read starting URL from environment *) - <Extract> the <start-url> from the <env: CRAWL_URL>. - <Log> "Starting URL: ${<start-url>}" to the <console>. + Extract the <start-url> from the <env: CRAWL_URL>. + Log "Starting URL: ${<start-url>}" to the <console>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -87,17 +87,17 @@ You should see both log messages, with the URL in the second one. ```aro (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. + Log "Starting Web Crawler..." to the <console>. - <Extract> the <start-url> from the <env: CRAWL_URL>. - <Log> "Starting URL: ${<start-url>}" to the <console>. + Extract the <start-url> from the <env: CRAWL_URL>. + Log "Starting URL: ${<start-url>}" to the <console>. (* Create output directory *) - <Create> the <output-path> with "./output". - <Make> the <output-dir> to the <directory: output-path>. - <Log> "Output directory created" to the <console>. + Create the <output-path> with "./output". + Make the <output-dir> to the <directory: output-path>. + Log "Output directory created" to the <console>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -107,19 +107,19 @@ You should see both log messages, with the URL in the second one. ```aro (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. + Log "Starting Web Crawler..." to the <console>. - <Extract> the <start-url> from the <env: CRAWL_URL>. - <Log> "Starting URL: ${<start-url>}" to the <console>. + Extract the <start-url> from the <env: CRAWL_URL>. + Log "Starting URL: ${<start-url>}" to the <console>. - <Create> the <output-path> with "./output". - <Make> the <output-dir> to the <directory: output-path>. - <Log> "Output directory created" to the <console>. + Create the <output-path> with "./output". + Make the <output-dir> to the <directory: output-path>. + Log "Output directory created" to the <console>. (* Queue initial URL for crawling *) - <Emit> a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. + Emit a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -137,8 +137,8 @@ Optionally, we can add a handler that runs when the application shuts down: ```aro (Application-End: Success) { - <Log> "🥁 Web Crawler completed!" to the <console>. - <Return> an <OK: status> for the <shutdown>. + Log "🥁 Web Crawler completed!" to the <console>. + Return an <OK: status> for the <shutdown>. } ``` @@ -158,27 +158,27 @@ Here is the complete entry point file: ============================================================ *) (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. + Log "Starting Web Crawler..." to the <console>. (* Read starting URL from environment *) - <Extract> the <start-url> from the <env: CRAWL_URL>. + Extract the <start-url> from the <env: CRAWL_URL>. - <Log> "Starting URL: ${<start-url>}" to the <console>. + Log "Starting URL: ${<start-url>}" to the <console>. (* Create output directory *) - <Create> the <output-path> with "./output". - <Make> the <output-dir> to the <directory: output-path>. - <Log> "Output directory created" to the <console>. + Create the <output-path> with "./output". + Make the <output-dir> to the <directory: output-path>. + Log "Output directory created" to the <console>. (* Queue initial URL - Emit blocks until the entire crawl chain completes *) - <Emit> a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. + Emit a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } (Application-End: Success) { - <Log> "🥁 Web Crawler completed!" to the <console>. - <Return> an <OK: status> for the <shutdown>. + Log "🥁 Web Crawler completed!" to the <console>. + Return an <OK: status> for the <shutdown>. } ``` @@ -205,7 +205,7 @@ Here is the complete entry point file: ## Chapter Recap - `Application-Start` is the entry point; exactly one must exist -- `<Extract> ... from the <env: VAR>` reads environment variables +- `Extract ... from the <env: VAR>` reads environment variables - `<Create>` makes values; `<Make>` creates filesystem objects - `<Emit>` sends events to trigger other feature sets and blocks until the chain completes - `Application-End: Success` runs automatically when `Application-Start` completes normally diff --git a/Book/AROByExample/Chapter04-EventDrivenArchitecture.md b/Book/AROByExample/Chapter04-EventDrivenArchitecture.md index 2b5cb71f..b8bed408 100644 --- a/Book/AROByExample/Chapter04-EventDrivenArchitecture.md +++ b/Book/AROByExample/Chapter04-EventDrivenArchitecture.md @@ -30,7 +30,7 @@ ARO takes a different approach. Code emits events, and other code listens for th ```aro (* In one file *) -<Emit> a <PageProcessed: event> with { content: <result>, url: <url> }. +Emit a <PageProcessed: event> with { content: <result>, url: <url> }. (* In another file, maybe added later *) (Save Content: PageProcessed Handler) { @@ -81,7 +81,7 @@ The runtime matches `{EventType} Handler` to events of type `EventType`. When a The `<Emit>` action sends an event to the event bus: ```aro -<Emit> a <CrawlPage: event> with { url: <url>, base: <domain> }. +Emit a <CrawlPage: event> with { url: <url>, base: <domain> }. ``` Breaking this down: @@ -95,13 +95,13 @@ The event data can contain any values: ```aro (* Simple values *) -<Emit> a <LogMessage: event> with { message: "Hello" }. +Emit a <LogMessage: event> with { message: "Hello" }. (* Multiple fields *) -<Emit> a <UserCreated: event> with { id: <user-id>, name: <name>, email: <email> }. +Emit a <UserCreated: event> with { id: <user-id>, name: <name>, email: <email> }. (* Nested data *) -<Emit> a <OrderPlaced: event> with { order: <order-data>, customer: <customer> }. +Emit a <OrderPlaced: event> with { order: <order-data>, customer: <customer> }. ``` --- @@ -113,23 +113,23 @@ When a handler receives an event, it extracts data using nested `<Extract>` acti ```aro (Process Order: OrderPlaced Handler) { (* First, extract the event data object *) - <Extract> the <event-data> from the <event: data>. + Extract the <event-data> from the <event: data>. (* Then, extract individual fields from the object *) - <Extract> the <order-id> from the <event-data: id>. - <Extract> the <customer-name> from the <event-data: customer>. + Extract the <order-id> from the <event-data: id>. + Extract the <customer-name> from the <event-data: customer>. (* Now use the extracted values *) - <Log> "Processing order ${<order-id>} for ${<customer-name>}" to the <console>. + Log "Processing order ${<order-id>} for ${<customer-name>}" to the <console>. - <Return> an <OK: status> for the <processing>. + Return an <OK: status> for the <processing>. } ``` The pattern is always: -1. `<Extract> the <event-data> from the <event: data>.` — Get the data object -2. `<Extract> the <field-name> from the <event-data: field>.` — Get each field +1. `Extract the <event-data> from the <event: data>.` — Get the data object +2. `Extract the <field-name> from the <event-data: field>.` — Get each field --- @@ -179,41 +179,41 @@ Let us write a simple two-handler pipeline to see this in action. Create a file ```aro (Application-Start: Event Demo) { - <Log> "Starting event demo..." to the <console>. + Log "Starting event demo..." to the <console>. (* Emit first event *) - <Emit> a <Greet: event> with { name: "World" }. + Emit a <Greet: event> with { name: "World" }. - <Log> "Event emitted, waiting..." to the <console>. - <Keepalive> the <application> for the <events>. + Log "Event emitted, waiting..." to the <console>. + Keepalive the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } (Say Hello: Greet Handler) { - <Log> "Greet handler triggered!" to the <console>. + Log "Greet handler triggered!" to the <console>. (* Extract the name from event data *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <name> from the <event-data: name>. + Extract the <event-data> from the <event: data>. + Extract the <name> from the <event-data: name>. - <Log> "Hello, ${<name>}!" to the <console>. + Log "Hello, ${<name>}!" to the <console>. (* Emit another event *) - <Emit> a <Farewell: event> with { name: <name> }. + Emit a <Farewell: event> with { name: <name> }. - <Return> an <OK: status> for the <greeting>. + Return an <OK: status> for the <greeting>. } (Say Goodbye: Farewell Handler) { - <Log> "Farewell handler triggered!" to the <console>. + Log "Farewell handler triggered!" to the <console>. - <Extract> the <event-data> from the <event: data>. - <Extract> the <name> from the <event-data: name>. + Extract the <event-data> from the <event: data>. + Extract the <name> from the <event-data: name>. - <Log> "Goodbye, ${<name>}!" to the <console>. + Log "Goodbye, ${<name>}!" to the <console>. - <Return> an <OK: status> for the <farewell>. + Return an <OK: status> for the <farewell>. } ``` @@ -252,7 +252,7 @@ Notice the flow: Start → Greet event → Hello handler → Farewell event → **No Event Tracing.** When something goes wrong, there is no built-in way to trace which events led to the error. You add `<Log>` statements manually. -**Event Schema Validation.** Event data is untyped by default. If a handler expects `name` but the emitter sends `userName`, you get a runtime error. However, ARO-0046 introduces **typed event extraction** which validates event data against OpenAPI schemas defined in `components.schemas`. See Chapter 6 for details on using `<Extract> the <data: SchemaName> from the <event: data>.` +**Event Schema Validation.** Event data is untyped by default. If a handler expects `name` but the emitter sends `userName`, you get a runtime error. However, ARO-0046 introduces **typed event extraction** which validates event data against OpenAPI schemas defined in `components.schemas`. See Chapter 6 for details on using `Extract the <data: SchemaName> from the <event: data>.` **No Guaranteed Order.** If multiple handlers listen to the same event, their execution order is not guaranteed. Usually this is fine, but sometimes order matters. diff --git a/Book/AROByExample/Chapter05-FetchingPages.md b/Book/AROByExample/Chapter05-FetchingPages.md index 923b2fa3..399a72ce 100644 --- a/Book/AROByExample/Chapter05-FetchingPages.md +++ b/Book/AROByExample/Chapter05-FetchingPages.md @@ -50,7 +50,7 @@ Create `crawler.aro` with the basic handler structure: ============================================================ *) (Crawl Page: CrawlPage Handler) { - <Return> an <OK: status> for the <crawl>. + Return an <OK: status> for the <crawl>. } ``` @@ -71,13 +71,13 @@ Add extraction of the URL and base domain: ```aro (Crawl Page: CrawlPage Handler) { (* Extract from event data *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. - <Log> "Crawling: ${<url>}" to the <console>. + Log "Crawling: ${<url>}" to the <console>. - <Return> an <OK: status> for the <crawl>. + Return an <OK: status> for the <crawl>. } ``` @@ -93,7 +93,7 @@ Now we fetch the actual content: (* Previous code... *) (* Fetch the page *) - <Request> the <html> from the <url>. + Request the <html> from the <url>. ``` `<Request>` makes an HTTP GET request and returns the response body. It is that simple. ARO handles redirects, HTTPS, and common errors automatically. @@ -108,9 +108,9 @@ The `<ParseHtml>` action converts HTML to structured data: (* Previous code... *) (* Extract markdown content from HTML using ParseHtml action *) - <ParseHtml> the <markdown-result: markdown> from the <html>. - <Extract> the <title> from the <markdown-result: title>. - <Extract> the <markdown-content> from the <markdown-result: markdown>. + ParseHtml the <markdown-result: markdown> from the <html>. + Extract the <title> from the <markdown-result: title>. + Extract the <markdown-content> from the <markdown-result: markdown>. ``` The `<ParseHtml>` action with the `markdown` specifier returns an object containing: @@ -130,12 +130,12 @@ Finally, we emit events for the next stages: (* Previous code... *) (* Save the markdown content to file *) - <Emit> a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. + Emit a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. (* Extract links from the HTML *) - <Emit> a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. + Emit a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. - <Return> an <OK: status> for the <crawl>. + Return an <OK: status> for the <crawl>. ``` We emit two events: @@ -160,17 +160,17 @@ Here is everything we have built: ============================================================ *) (Crawl Page: CrawlPage Handler) { - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. - <Log> "Crawling: ${<url>}" to the <console>. - <Request> the <html> from the <url>. - <ParseHtml> the <markdown-result: markdown> from the <html>. - <Extract> the <title> from the <markdown-result: title>. - <Extract> the <markdown-content> from the <markdown-result: markdown>. - <Emit> a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. - <Emit> a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. - <Return> an <OK: status> for the <crawl>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. + Log "Crawling: ${<url>}" to the <console>. + Request the <html> from the <url>. + ParseHtml the <markdown-result: markdown> from the <html>. + Extract the <title> from the <markdown-result: title>. + Extract the <markdown-content> from the <markdown-result: markdown>. + Emit a <SavePage: event> with { url: <url>, title: <title>, content: <markdown-content>, base: <base-domain> }. + Emit a <ExtractLinks: event> with { url: <url>, html: <html>, base: <base-domain> }. + Return an <OK: status> for the <crawl>. } ``` @@ -180,7 +180,7 @@ Eleven lines. Extract, log, fetch, parse, emit, return. Every line does exactly ## 5.9 What ARO Does Well Here -**Simple HTTP.** `<Request> the <html> from the <url>.` -- One line for HTTP GET. No client setup, no promise handling, no error callbacks. +**Simple HTTP.** `Request the <html> from the <url>.` -- One line for HTTP GET. No client setup, no promise handling, no error callbacks. **Built-in HTML Parsing.** The `<ParseHtml>` action handles real-world HTML. It extracts titles, converts content, and produces clean Markdown without external libraries. @@ -203,7 +203,7 @@ Eleven lines. Extract, log, fetch, parse, emit, return. Every line does exactly - The `CrawlPage` handler is the core of our crawler - Deduplication is handled upstream by `QueueUrl`, keeping this handler focused - `<Request>` makes HTTP requests; the response body is returned directly -- `<ParseHtml> ... markdown` converts HTML to Markdown and extracts the title +- `ParseHtml ... markdown` converts HTML to Markdown and extracts the title - We emit `SavePage` and `ExtractLinks` events for downstream handlers - Event-driven design lets each handler focus on a single responsibility diff --git a/Book/AROByExample/Chapter06-LinkExtraction.md b/Book/AROByExample/Chapter06-LinkExtraction.md index c438afa1..a53bd916 100644 --- a/Book/AROByExample/Chapter06-LinkExtraction.md +++ b/Book/AROByExample/Chapter06-LinkExtraction.md @@ -51,7 +51,7 @@ The `<ParseHtml>` action supports multiple specifiers: We have already used `markdown` in the crawl handler. Now we will use `links`: ```aro -<ParseHtml> the <links: links> from the <html>. +ParseHtml the <links: links> from the <html>. ``` This returns a list like: @@ -75,15 +75,15 @@ Create `links.aro` with the `ExtractLinks` handler: ============================================================ *) (Extract Links: ExtractLinks Handler) { - <Log> "ExtractLinks handler triggered" to the <console>. + Log "ExtractLinks handler triggered" to the <console>. (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } ``` @@ -129,12 +129,12 @@ With the schema defined, the handler becomes: ```aro (Extract Links: ExtractLinks Handler) { - <Log> "ExtractLinks handler triggered" to the <console>. + Log "ExtractLinks handler triggered" to the <console>. (* Typed extraction - validates against ExtractLinksEvent schema *) - <Extract> the <event-data: ExtractLinksEvent> from the <event: data>. + Extract the <event-data: ExtractLinksEvent> from the <event: data>. - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } ``` @@ -148,8 +148,8 @@ The PascalCase qualifier `ExtractLinksEvent` tells ARO to: After typed extraction, access properties using the qualifier syntax: ```aro -<ParseHtml> the <links: links> from the <event-data: html>. -<Log> "Processing links from ${<event-data: url>}" to the <console>. +ParseHtml the <links: links> from the <event-data: html>. +Log "Processing links from ${<event-data: url>}" to the <console>. ``` ### Typed vs Field-by-Field @@ -169,19 +169,19 @@ Add the link extraction: ```aro (Extract Links: ExtractLinks Handler) { - <Log> "ExtractLinks handler triggered" to the <console>. + Log "ExtractLinks handler triggered" to the <console>. - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Use ParseHtml action to extract all href attributes from anchor tags *) - <ParseHtml> the <links: links> from the <html>. - <Compute> the <link-count: count> from the <links>. - <Log> "Found ${<link-count>} links" to the <console>. + ParseHtml the <links: links> from the <html>. + Compute the <link-count: count> from the <links>. + Log "Found ${<link-count>} links" to the <console>. - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } ``` @@ -198,14 +198,14 @@ To process each link, we use `for each`: (* Process each extracted link *) for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { + Emit a <NormalizeUrl: event> with { raw: <raw-url>, source: <source-url>, base: <base-domain> }. } - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. ``` The `for each` loop iterates over the list. For each item, it binds that item to `raw-url` and executes the block. @@ -224,7 +224,7 @@ In Chapter 10, we will replace `for each` with `parallel for each`: ```aro parallel for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { ... }. + Emit a <NormalizeUrl: event> with { ... }. } ``` @@ -244,29 +244,29 @@ Here is the complete `ExtractLinks` handler: ============================================================ *) (Extract Links: ExtractLinks Handler) { - <Log> "ExtractLinks handler triggered" to the <console>. + Log "ExtractLinks handler triggered" to the <console>. (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Use ParseHtml action to extract all href attributes from anchor tags *) - <ParseHtml> the <links: links> from the <html>. - <Compute> the <link-count: count> from the <links>. - <Log> "Found ${<link-count>} links" to the <console>. + ParseHtml the <links: links> from the <html>. + Compute the <link-count: count> from the <links>. + Log "Found ${<link-count>} links" to the <console>. (* Process each extracted link using for each *) for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { + Emit a <NormalizeUrl: event> with { raw: <raw-url>, source: <source-url>, base: <base-domain> }. } - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } ``` @@ -292,9 +292,9 @@ Here is the complete `ExtractLinks` handler: ## Chapter Recap -- `<ParseHtml> ... links` extracts all href values from anchor tags +- `ParseHtml ... links` extracts all href values from anchor tags - The result is a list of raw strings (relative and absolute URLs, fragments, etc.) -- Typed event extraction (`<Extract> the <data: SchemaName> from <event>`) validates data against OpenAPI schemas +- Typed event extraction (`Extract the <data: SchemaName> from <event>`) validates data against OpenAPI schemas - `for each <item> in <list>` iterates over collections - We emit a `NormalizeUrl` event for each link, passing through the source and base - This handler is focused: extract and emit, nothing more diff --git a/Book/AROByExample/Chapter07-URLNormalization.md b/Book/AROByExample/Chapter07-URLNormalization.md index d79e7367..37d40f16 100644 --- a/Book/AROByExample/Chapter07-URLNormalization.md +++ b/Book/AROByExample/Chapter07-URLNormalization.md @@ -71,12 +71,12 @@ Add to `links.aro`: ```aro (Normalize URL: NormalizeUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <raw-url> from the <event-data: raw>. - <Extract> the <source-url> from the <event-data: source>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <raw-url> from the <event-data: raw>. + Extract the <source-url> from the <event-data: source>. + Extract the <base-domain> from the <event-data: base>. - <Return> an <OK: status> for the <normalization>. + Return an <OK: status> for the <normalization>. } ``` @@ -101,24 +101,24 @@ Similarly, `https://example.com/page/` and `https://example.com/page` are typica ```aro (Normalize URL: NormalizeUrl Handler) { - <Extract> the <event-data> from the <event: data>. - <Extract> the <raw-url> from the <event-data: raw>. - <Extract> the <source-url> from the <event-data: source>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <raw-url> from the <event-data: raw>. + Extract the <source-url> from the <event-data: source>. + Extract the <base-domain> from the <event-data: base>. (* Determine URL type and normalize *) match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } } - <Return> an <OK: status> for the <normalization>. + Return an <OK: status> for the <normalization>. } ``` @@ -134,14 +134,14 @@ If the URL starts with `http://` or `https://`, we clean it before emitting to t The cleaning logic above introduces a new action: `<Split>`. It splits a string into a list using a regex delimiter: ```aro -<Split> the <parts> from the <string> by /regex/. +Split the <parts> from the <string> by /regex/. ``` The result is a list of substrings. You can then use `<Extract>` with the `first` specifier to get the first element: ```aro -<Split> the <parts> from the <url> by /#/. -<Extract> the <before-hash: first> from the <parts>. +Split the <parts> from the <url> by /#/. +Extract the <before-hash: first> from the <parts>. ``` Given `"https://example.com/page#section"`, the split on `/#/` produces `["https://example.com/page", "section"]`. Extracting the first element gives us `"https://example.com/page"` -- the URL without its fragment. @@ -149,8 +149,8 @@ Given `"https://example.com/page#section"`, the split on `/#/` produces `["https For trailing slash removal, we split on the pattern `/\/+$/`, which matches one or more slashes at the end of the string: ```aro -<Split> the <parts> from the <url> by /\/+$/. -<Extract> the <clean: first> from the <parts>. +Split the <parts> from the <url> by /\/+$/. +Extract the <clean: first> from the <parts>. ``` Given `"https://example.com/page/"`, the split produces `["https://example.com/page"]`. If there is no trailing slash, the split produces the original string as a single-element list, so the logic works in both cases. @@ -165,24 +165,24 @@ Root-relative URLs like `/about` need the base domain prepended. After joining, match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^\/$/ { (* Just "/" means root - use base domain as-is (no trailing slash) *) - <Emit> a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. + Emit a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. } case /^\// { (* Root-relative URL: prepend base domain, strip fragment and trailing slash *) - <Create> the <joined-url> with "${<base-domain>}${<raw-url>}". - <Split> the <frag-parts> from the <joined-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Create the <joined-url> with "${<base-domain>}${<raw-url>}". + Split the <frag-parts> from the <joined-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } } ``` @@ -207,24 +207,24 @@ Fragments and special schemes should not be crawled: match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^\/$/ { (* Just "/" means root - use base domain as-is (no trailing slash) *) - <Emit> a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. + Emit a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. } case /^\// { (* Root-relative URL: prepend base domain, strip fragment and trailing slash *) - <Create> the <joined-url> with "${<base-domain>}${<raw-url>}". - <Split> the <frag-parts> from the <joined-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Create the <joined-url> with "${<base-domain>}${<raw-url>}". + Split the <frag-parts> from the <joined-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^(#|mailto:|javascript:|tel:|data:)/ { (* Skip fragments and special URLs *) @@ -248,39 +248,39 @@ For these, we do nothing—no emit, no error. They silently disappear from the p ```aro (Normalize URL: NormalizeUrl Handler) { - <Extract> the <event-data> from the <event: data>. - <Extract> the <raw-url> from the <event-data: raw>. - <Extract> the <source-url> from the <event-data: source>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <raw-url> from the <event-data: raw>. + Extract the <source-url> from the <event-data: source>. + Extract the <base-domain> from the <event-data: base>. match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^\/$/ { (* Just "/" means root - use base domain as-is (no trailing slash) *) - <Emit> a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. + Emit a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. } case /^\// { (* Root-relative URL: prepend base domain, strip fragment and trailing slash *) - <Create> the <joined-url> with "${<base-domain>}${<raw-url>}". - <Split> the <frag-parts> from the <joined-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Create the <joined-url> with "${<base-domain>}${<raw-url>}". + Split the <frag-parts> from the <joined-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^(#|mailto:|javascript:|tel:|data:)/ { (* Skip fragments and special URLs *) } } - <Return> an <OK: status> for the <normalization>. + Return an <OK: status> for the <normalization>. } ``` @@ -319,7 +319,7 @@ For simplicity, our crawler skips them. They fall through the `match` without em - URLs come in many forms: absolute, root-relative, path-relative, fragments, special schemes - `match` with regex patterns classifies URLs cleanly - `<Split>` with regex delimiters breaks strings into lists -- useful for stripping URL fragments and trailing slashes -- `<Extract> first` retrieves the first element from a list produced by `<Split>` +- `Extract first` retrieves the first element from a list produced by `<Split>` - Fragment stripping (`#section`) and trailing slash removal prevent duplicate crawling of the same page - String interpolation `"${<var>}"` builds absolute URLs from base domain and path - Non-web URLs are filtered by not emitting events diff --git a/Book/AROByExample/Chapter08-URLFiltering.md b/Book/AROByExample/Chapter08-URLFiltering.md index 4e2d3ae4..81e6e390 100644 --- a/Book/AROByExample/Chapter08-URLFiltering.md +++ b/Book/AROByExample/Chapter08-URLFiltering.md @@ -40,7 +40,7 @@ The `FilterUrl` handler decides which URLs proceed to the queue. ARO has a powerful construct for conditional execution: the `when` guard. ```aro -<Emit> a <SomeEvent: event> with <data> when <condition>. +Emit a <SomeEvent: event> with <data> when <condition>. ``` The action only executes if the condition is true. This is not an if/else—there is no else branch. If the condition is false, the statement is simply skipped. @@ -49,13 +49,13 @@ Guards can use various conditions: ```aro (* String containment *) -<Action> ... when <string> contains <substring>. +Action ... when <string> contains <substring>. (* Numeric comparison *) -<Action> ... when <count> > 0. +Action ... when <count> > 0. (* Equality *) -<Action> ... when <status> = "active". +Action ... when <status> = "active". ``` --- @@ -67,11 +67,11 @@ Add to `links.aro`: ```aro (Filter URL: FilterUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. - <Return> an <OK: status> for the <filter>. + Return an <OK: status> for the <filter>. } ``` @@ -89,14 +89,14 @@ Now add the conditional emit: ```aro (Filter URL: FilterUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Filter URLs that belong to the same domain as base-domain *) - <Emit> a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. + Emit a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. - <Return> an <OK: status> for the <filter>. + Return an <OK: status> for the <filter>. } ``` @@ -127,15 +127,15 @@ However, there are edge cases. `https://example.com.malicious.com` would match b ```aro (Filter URL: FilterUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Filter URLs that belong to the same domain as base-domain *) - <Log> "Queuing: ${<url>}" to the <console> when <url> contains <base-domain>. - <Emit> a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. + Log "Queuing: ${<url>}" to the <console> when <url> contains <base-domain>. + Emit a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. - <Return> an <OK: status> for the <filter>. + Return an <OK: status> for the <filter>. } ``` @@ -150,30 +150,30 @@ The final handler in the link pipeline queues URLs for crawling. Add to `links.a ```aro (Queue URL: QueueUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Generate deterministic id from URL hash for deduplication *) - <Compute> the <url-id: hash> from the <url>. + Compute the <url-id: hash> from the <url>. (* Store with id - repository deduplicates by id, observer only fires for new entries *) - <Create> the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. - <Store> the <crawl-request> into the <crawled-repository>. + Create the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. + Store the <crawl-request> into the <crawled-repository>. - <Return> an <OK: status> for the <queue>. + Return an <OK: status> for the <queue>. } (Trigger Crawl: crawled-repository Observer) { (* React to new entries in the repository *) - <Extract> the <crawl-request> from the <event: newValue>. - <Extract> the <url> from the <crawl-request: url>. - <Extract> the <base-domain> from the <crawl-request: base>. + Extract the <crawl-request> from the <event: newValue>. + Extract the <url> from the <crawl-request: url>. + Extract the <base-domain> from the <crawl-request: base>. - <Log> "Queued: ${<url>}" to the <console>. - <Emit> a <CrawlPage: event> with { url: <url>, base: <base-domain> }. + Log "Queued: ${<url>}" to the <console>. + Emit a <CrawlPage: event> with { url: <url>, base: <base-domain> }. - <Return> an <OK: status> for the <observer>. + Return an <OK: status> for the <observer>. } ``` @@ -201,102 +201,102 @@ We now have four handlers plus one observer in `links.aro`. Here is the complete (Extract Links: ExtractLinks Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Use ParseHtml action to extract all href attributes from anchor tags *) - <ParseHtml> the <links: links> from the <html>. + ParseHtml the <links: links> from the <html>. (* Process links in parallel - repository Actor ensures atomic dedup *) parallel for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { + Emit a <NormalizeUrl: event> with { raw: <raw-url>, source: <source-url>, base: <base-domain> }. } - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } (Normalize URL: NormalizeUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <raw-url> from the <event-data: raw>. - <Extract> the <source-url> from the <event-data: source>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <raw-url> from the <event-data: raw>. + Extract the <source-url> from the <event-data: source>. + Extract the <base-domain> from the <event-data: base>. (* Determine URL type and normalize *) match <raw-url> { case /^https?:\/\// { (* Already absolute URL - strip fragment and trailing slash *) - <Split> the <frag-parts> from the <raw-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Split the <frag-parts> from the <raw-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^\/$/ { (* Just "/" means root - use base domain as-is (no trailing slash) *) - <Emit> a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. + Emit a <FilterUrl: event> with { url: <base-domain>, base: <base-domain> }. } case /^\// { (* Root-relative URL: prepend base domain, strip fragment and trailing slash *) - <Create> the <joined-url> with "${<base-domain>}${<raw-url>}". - <Split> the <frag-parts> from the <joined-url> by /#/. - <Extract> the <no-fragment: first> from the <frag-parts>. - <Split> the <slash-parts> from the <no-fragment> by /\/+$/. - <Extract> the <clean-url: first> from the <slash-parts>. - <Emit> a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. + Create the <joined-url> with "${<base-domain>}${<raw-url>}". + Split the <frag-parts> from the <joined-url> by /#/. + Extract the <no-fragment: first> from the <frag-parts>. + Split the <slash-parts> from the <no-fragment> by /\/+$/. + Extract the <clean-url: first> from the <slash-parts>. + Emit a <FilterUrl: event> with { url: <clean-url>, base: <base-domain> }. } case /^(#|mailto:|javascript:|tel:|data:)/ { (* Skip fragments and special URLs *) } } - <Return> an <OK: status> for the <normalization>. + Return an <OK: status> for the <normalization>. } (Filter URL: FilterUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Filter URLs that belong to the same domain as base-domain *) - <Emit> a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. + Emit a <QueueUrl: event> with { url: <url>, base: <base-domain> } when <url> contains <base-domain>. - <Return> an <OK: status> for the <filter>. + Return an <OK: status> for the <filter>. } (Queue URL: QueueUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Generate deterministic id from URL hash for deduplication *) - <Compute> the <url-id: hash> from the <url>. + Compute the <url-id: hash> from the <url>. (* Store with id - repository deduplicates by id, observer only fires for new entries *) - <Create> the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. - <Store> the <crawl-request> into the <crawled-repository>. + Create the <crawl-request> with { id: <url-id>, url: <url>, base: <base-domain> }. + Store the <crawl-request> into the <crawled-repository>. - <Return> an <OK: status> for the <queue>. + Return an <OK: status> for the <queue>. } (Trigger Crawl: crawled-repository Observer) { (* React to new entries in the repository *) - <Extract> the <crawl-request> from the <event: newValue>. - <Extract> the <url> from the <crawl-request: url>. - <Extract> the <base-domain> from the <crawl-request: base>. + Extract the <crawl-request> from the <event: newValue>. + Extract the <url> from the <crawl-request: url>. + Extract the <base-domain> from the <crawl-request: base>. - <Log> "Queued: ${<url>}" to the <console>. - <Emit> a <CrawlPage: event> with { url: <url>, base: <base-domain> }. + Log "Queued: ${<url>}" to the <console>. + Emit a <CrawlPage: event> with { url: <url>, base: <base-domain> }. - <Return> an <OK: status> for the <observer>. + Return an <OK: status> for the <observer>. } ``` diff --git a/Book/AROByExample/Chapter09-StoringResults.md b/Book/AROByExample/Chapter09-StoringResults.md index 355eac75..70705a23 100644 --- a/Book/AROByExample/Chapter09-StoringResults.md +++ b/Book/AROByExample/Chapter09-StoringResults.md @@ -50,12 +50,12 @@ Create `storage.aro`: (Save Page: SavePage Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <title> from the <event-data: title>. - <Extract> the <content> from the <event-data: content>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <title> from the <event-data: title>. + Extract the <content> from the <event-data: content>. - <Return> an <OK: status> for the <save>. + Return an <OK: status> for the <save>. } ``` @@ -73,22 +73,22 @@ Add the hash computation: ```aro (Save Page: SavePage Handler) { - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <title> from the <event-data: title>. - <Extract> the <content> from the <event-data: content>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <title> from the <event-data: title>. + Extract the <content> from the <event-data: content>. (* Use URL hash as filename *) - <Compute> the <url-hash: hash> from the <url>. - <Create> the <file-path> with "./output/${<url-hash>}.md". + Compute the <url-hash: hash> from the <url>. + Create the <file-path> with "./output/${<url-hash>}.md". - <Log> "Saving: ${<url>} to ${<file-path>}" to the <console>. + Log "Saving: ${<url>} to ${<file-path>}" to the <console>. - <Return> an <OK: status> for the <save>. + Return an <OK: status> for the <save>. } ``` -The `<Compute> ... hash` operation generates a hash from the URL string. We then build the file path using string interpolation. +The `Compute ... hash` operation generates a hash from the URL string. We then build the file path using string interpolation. --- @@ -100,7 +100,7 @@ We want each file to include metadata about the source: (* Previous code... *) (* Format markdown file with frontmatter *) - <Create> the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". + Create the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". ``` This creates Markdown like: @@ -127,9 +127,9 @@ Finally, write the content: (* Previous code... *) (* Write content to file *) - <Write> the <file-content> to the <file: file-path>. + Write the <file-content> to the <file: file-path>. - <Return> an <OK: status> for the <save>. + Return an <OK: status> for the <save>. } ``` @@ -149,24 +149,24 @@ The `<Write>` action writes a string to a file. The `<file: ...>` specifier indi (Save Page: SavePage Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <title> from the <event-data: title>. - <Extract> the <content> from the <event-data: content>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <title> from the <event-data: title>. + Extract the <content> from the <event-data: content>. (* Use URL hash as filename *) - <Compute> the <url-hash: hash> from the <url>. - <Create> the <file-path> with "./output/${<url-hash>}.md". + Compute the <url-hash: hash> from the <url>. + Create the <file-path> with "./output/${<url-hash>}.md". - <Log> "Saving: ${<url>} to ${<file-path>}" to the <console>. + Log "Saving: ${<url>} to ${<file-path>}" to the <console>. (* Format markdown file with frontmatter *) - <Create> the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". + Create the <file-content> with "# ${<title>}\n\n**Source:** ${<url>}\n\n---\n\n${<content>}". (* Write content to file *) - <Write> the <file-content> to the <file: file-path>. + Write the <file-content> to the <file: file-path>. - <Return> an <OK: status> for the <save>. + Return an <OK: status> for the <save>. } ``` @@ -224,7 +224,7 @@ The hash filename is not human-readable, but the content preserves the source UR ## Chapter Recap -- `<Compute> ... hash` generates a hash from a string +- `Compute ... hash` generates a hash from a string - Hash-based filenames ensure uniqueness across all URLs - `<Create>` with `\n` builds multi-line content - `<Write>` saves content to a file path diff --git a/Book/AROByExample/Chapter10-ParallelProcessing.md b/Book/AROByExample/Chapter10-ParallelProcessing.md index 417ea9d9..34b32a79 100644 --- a/Book/AROByExample/Chapter10-ParallelProcessing.md +++ b/Book/AROByExample/Chapter10-ParallelProcessing.md @@ -19,7 +19,7 @@ In Chapter 6, we used `for each` to process links: ```aro for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { ... }. + Emit a <NormalizeUrl: event> with { ... }. } ``` @@ -60,24 +60,24 @@ Change the `for each` to `parallel for each` in `links.aro`: ```aro (Extract Links: ExtractLinks Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <html> from the <event-data: html>. - <Extract> the <source-url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <html> from the <event-data: html>. + Extract the <source-url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Use ParseHtml action to extract all href attributes from anchor tags *) - <ParseHtml> the <links: links> from the <html>. + ParseHtml the <links: links> from the <html>. (* Process links in parallel - repository Actor ensures atomic dedup *) parallel for each <raw-url> in <links> { - <Emit> a <NormalizeUrl: event> with { + Emit a <NormalizeUrl: event> with { raw: <raw-url>, source: <source-url>, base: <base-domain> }. } - <Return> an <OK: status> for the <extraction>. + Return an <OK: status> for the <extraction>. } ``` diff --git a/Book/AROByExample/Chapter11-SetOperations.md b/Book/AROByExample/Chapter11-SetOperations.md index a0027921..194587d0 100644 --- a/Book/AROByExample/Chapter11-SetOperations.md +++ b/Book/AROByExample/Chapter11-SetOperations.md @@ -38,9 +38,9 @@ ARO provides three key set operations through `<Compute>`: | Operation | Syntax | Result | |-----------|--------|--------| -| `union` | `<Compute> the <result: union> from <set-a> with <set-b>.` | All items from both sets | -| `difference` | `<Compute> the <result: difference> from <set-a> with <set-b>.` | Items in set-a but not in set-b | -| `count` | `<Compute> the <result: count> from <set>.` | Number of items | +| `union` | `Compute the <result: union> from <set-a> with <set-b>.` | All items from both sets | +| `difference` | `Compute the <result: difference> from <set-a> with <set-b>.` | Items in set-a but not in set-b | +| `count` | `Compute the <result: count> from <set>.` | Number of items | These operations treat lists as sets—duplicate items within a list are considered once. @@ -51,16 +51,16 @@ These operations treat lists as sets—duplicate items within a list are conside Union combines two sets: ```aro -<Create> the <set-a> with ["apple", "banana"]. -<Create> the <set-b> with ["banana", "cherry"]. -<Compute> the <combined: union> from <set-a> with <set-b>. +Create the <set-a> with ["apple", "banana"]. +Create the <set-b> with ["banana", "cherry"]. +Compute the <combined: union> from <set-a> with <set-b>. (* combined = ["apple", "banana", "cherry"] *) ``` In our crawler, we use union to add new URLs to the crawled set: ```aro -<Compute> the <updated-crawled: union> from <crawled-urls> with <single-url-list>. +Compute the <updated-crawled: union> from <crawled-urls> with <single-url-list>. ``` This adds the new URL to the existing set of crawled URLs. @@ -72,18 +72,18 @@ This adds the new URL to the existing set of crawled URLs. Difference finds items in one set but not another: ```aro -<Create> the <all-urls> with ["a", "b", "c"]. -<Create> the <crawled> with ["a", "c"]. -<Compute> the <uncrawled: difference> from <all-urls> with <crawled>. +Create the <all-urls> with ["a", "b", "c"]. +Create the <crawled> with ["a", "c"]. +Compute the <uncrawled: difference> from <all-urls> with <crawled>. (* uncrawled = ["b"] *) ``` In our crawler, we use difference to check if a URL is new: ```aro -<Create> the <single-url-list> with [<url>]. -<Compute> the <new-urls: difference> from <single-url-list> with <crawled-urls>. -<Compute> the <new-url-count: count> from <new-urls>. +Create the <single-url-list> with [<url>]. +Compute the <new-urls: difference> from <single-url-list> with <crawled-urls>. +Compute the <new-url-count: count> from <new-urls>. ``` If `new-url-count` is 0, the URL is already in `crawled-urls`. If it is 1, the URL is new. @@ -96,10 +96,10 @@ Handlers are stateless—they execute and end. To persist data across handler ex ```aro (* Store data *) -<Store> the <value> into the <repository-name>. +Store the <value> into the <repository-name>. (* Retrieve data *) -<Retrieve> the <value> from the <repository-name>. +Retrieve the <value> from the <repository-name>. ``` Repository names are arbitrary identifiers. In our crawler, we use `crawled-repository` to store the set of crawled URLs. @@ -120,25 +120,25 @@ The set operations from Sections 11.4 and 11.5 can be combined into a general-pu ```aro (* 1. Retrieve the current set *) -<Retrieve> the <crawled-urls> from the <crawled-repository>. +Retrieve the <crawled-urls> from the <crawled-repository>. (* 2. Wrap the new URL in a list *) -<Create> the <single-url-list> with [<url>]. +Create the <single-url-list> with [<url>]. (* 3. Check if it's new *) -<Compute> the <new-urls: difference> from <single-url-list> with <crawled-urls>. -<Compute> the <new-url-count: count> from <new-urls>. +Compute the <new-urls: difference> from <single-url-list> with <crawled-urls>. +Compute the <new-url-count: count> from <new-urls>. (* 4. If count is 0, URL is already crawled *) match <new-url-count> { case 0 { - <Return> an <OK: status> for the <skip>. + Return an <OK: status> for the <skip>. } } (* 5. Add URL to crawled set *) -<Compute> the <updated-crawled: union> from <crawled-urls> with <single-url-list>. -<Store> the <updated-crawled> into the <crawled-repository>. +Compute the <updated-crawled: union> from <crawled-urls> with <single-url-list>. +Store the <updated-crawled> into the <crawled-repository>. (* 6. Proceed with crawling *) ``` @@ -159,19 +159,19 @@ Here is the pattern our crawler actually uses: ```aro (Queue URL: QueueUrl Handler) { (* Extract from event data structure *) - <Extract> the <event-data> from the <event: data>. - <Extract> the <url> from the <event-data: url>. - <Extract> the <base-domain> from the <event-data: base>. + Extract the <event-data> from the <event: data>. + Extract the <url> from the <event-data: url>. + Extract the <base-domain> from the <event-data: base>. (* Atomic store - the repository Actor serializes concurrent access, so only the first caller for a given URL gets is-new-entry = 1 *) - <Store> the <url> into the <crawled-repository>. + Store the <url> into the <crawled-repository>. (* Only emit CrawlPage if this URL was newly stored *) - <Log> "Queued: ${<url>}" to the <console> when <new-entry> > 0. - <Emit> a <CrawlPage: event> with { url: <url>, base: <base-domain> } when <new-entry> > 0. + Log "Queued: ${<url>}" to the <console> when <new-entry> > 0. + Emit a <CrawlPage: event> with { url: <url>, base: <base-domain> } when <new-entry> > 0. - <Return> an <OK: status> for the <queue>. + Return an <OK: status> for the <queue>. } ``` diff --git a/Book/AROByExample/Chapter12-PuttingItTogether.md b/Book/AROByExample/Chapter12-PuttingItTogether.md index 66988adc..eac035eb 100644 --- a/Book/AROByExample/Chapter12-PuttingItTogether.md +++ b/Book/AROByExample/Chapter12-PuttingItTogether.md @@ -195,19 +195,19 @@ Here are all four files for reference: **main.aro** (13 lines) ```aro (Application-Start: Web Crawler) { - <Log> "Starting Web Crawler..." to the <console>. - <Extract> the <start-url> from the <env: CRAWL_URL>. - <Log> "Starting URL: ${<start-url>}" to the <console>. - <Create> the <output-path> with "./output". - <Make> the <output-dir> to the <directory: output-path>. - <Log> "Output directory created" to the <console>. - <Emit> a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. - <Return> an <OK: status> for the <startup>. + Log "Starting Web Crawler..." to the <console>. + Extract the <start-url> from the <env: CRAWL_URL>. + Log "Starting URL: ${<start-url>}" to the <console>. + Create the <output-path> with "./output". + Make the <output-dir> to the <directory: output-path>. + Log "Output directory created" to the <console>. + Emit a <QueueUrl: event> with { url: <start-url>, base: <start-url> }. + Return an <OK: status> for the <startup>. } (Application-End: Success) { - <Log> "Web Crawler completed!" to the <console>. - <Return> an <OK: status> for the <shutdown>. + Log "Web Crawler completed!" to the <console>. + Return an <OK: status> for the <shutdown>. } ``` diff --git a/Book/AROByExample/Chapter14-WhatsNext.md b/Book/AROByExample/Chapter14-WhatsNext.md index 1cf12270..8b1b7824 100644 --- a/Book/AROByExample/Chapter14-WhatsNext.md +++ b/Book/AROByExample/Chapter14-WhatsNext.md @@ -39,7 +39,7 @@ Here are ideas for extending what you built: Track how many links deep you have traveled from the starting URL. Stop crawling after a certain depth to limit the scope. ```aro -<Emit> a <CrawlPage: event> with { url: <url>, base: <base>, depth: <current-depth> }. +Emit a <CrawlPage: event> with { url: <url>, base: <base>, depth: <current-depth> }. ``` **Rate Limiting** @@ -47,7 +47,7 @@ Track how many links deep you have traveled from the starting URL. Stop crawling Add delays between requests to avoid overwhelming servers. ARO has a `<Wait>` action: ```aro -<Wait> for 1000. (* milliseconds *) +Wait for 1000. (* milliseconds *) ``` **Content Filtering** @@ -55,7 +55,7 @@ Add delays between requests to avoid overwhelming servers. ARO has a `<Wait>` ac Skip pages based on URL patterns, content type, or page size: ```aro -<Request> the <html> from the <url> when <url> contains "/docs/". +Request the <html> from the <url> when <url> contains "/docs/". ``` **Robots.txt Compliance** @@ -82,8 +82,8 @@ ARO can serve HTTP APIs using OpenAPI contracts: ```aro (listUsers: User API) { - <Retrieve> the <users> from the <user-repository>. - <Return> an <OK: status> with <users>. + Retrieve the <users> from the <user-repository>. + Return an <OK: status> with <users>. } ``` @@ -95,13 +95,13 @@ Watch a directory for new files and process them: ```aro (Application-Start: File Processor) { - <Start> the <file-monitor> with "./inbox". - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Start the <file-monitor> with "./inbox". + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } (Process File: File Event Handler) { - <Extract> the <path> from the <event: path>. + Extract the <path> from the <event: path>. (* Process the file *) } ``` diff --git a/Book/Reference/Actions.md b/Book/Reference/Actions.md index e159c684..96396df7 100644 --- a/Book/Reference/Actions.md +++ b/Book/Reference/Actions.md @@ -4,55 +4,55 @@ Complete reference of all 51 ARO actions organized by category. | **Action** | **Category** | **Semantic Role** | **Description** | | ------------- | ----------------- | ----------------- | --------------------------------------------------------- | -| **Send** | Communication | RESPONSE | Delivers data or message outward.<br>`<Send> "Hello" to the <connection>.` | -| **Receive** | Communication | REQUEST | Accepts incoming data or message from external source.<br>`<Receive> the <message> from the <event>.` | -| **Request** | Communication | REQUEST | Initiates a query or ask for data or service.<br>`<Request> the <data> from the <api-url>.` | -| **Listen** | Communication | OWN | Waits for incoming events or data.<br>`<Listen> on port 9000 as <socket-server>.` | -| **Connect** | Communication | OWN | Establishes a link between endpoints.<br>`<Connect> to <host: "localhost"> on port 5432 as <db>.` | -| **Close** | Communication | OWN | Terminates a connection or handle.<br>`<Close> the <database-connection>.` | -| **Keepalive** | Communication | OWN | Maintains an active connection.<br>`<Keepalive> the <application> for the <events>.` | -| **Notify** | Communication | RESPONSE | Signals a change or event to observers.<br>`<Notify> the <alert> to the <admin>.` | -| **Broadcast** | Communication | RESPONSE | Sends to multiple recipients.<br>`<Broadcast> the <message> to the <socket-server>.` | -| **Publish** | Communication | EXPORT | Publishes an event or message to a channel.<br>`<Publish> as <app-config> <config>.` | -| **Emit** | Communication | EXPORT | Emits an event or signal.<br>`<Emit> a <UserCreated: event> with <user>.` | -| **Make** | Construction | OWN | Builds or prepares a resource (e.g., dirs).<br>`<Make> the <output-dir> to the <path: "./output">.` | -| **Execute** | Control | OWN | Runs a command or code block.<br>`<Execute> the <result> for the <command: "ls"> with "-la".` | -| **Call** | Control | OWN | Invokes a function or service.<br>`<Call> the <result> via <API: POST /users> with <data>.` | -| **Return** | Control | RESPONSE | Sends back a result from a call.<br>`<Return> an <OK: status> with <data>.` | -| **Given** | Control/Spec | OWN | Denotes initial precondition in scenarios.<br>`<Given> the <user> with { name: "Test" }.` | -| **When** | Control/Spec | OWN | Denotes conditional trigger.<br>`<When> the <action> from the <feature-set>.` | -| **Then** | Control/Spec | OWN | Denotes expected result after condition.<br>`<Then> the <result> with <expected>.` | -| **Extract** | Data Access | REQUEST | Pulls a subset or component from a larger data structure. PascalCase qualifiers enable typed extraction with OpenAPI schema validation (ARO-0046).<br>`<Extract> the <user-id> from the <request: parameters>.`<br>`<Extract> the <data: UserEvent> from the <event: data>.` | -| **Retrieve** | Data Access | REQUEST | Gets existing data by key or identifier.<br>`<Retrieve> the <user> from the <user-repository> where id = <id>.` | -| **List** | Enumeration | REQUEST | Enumerates items in a collection or directory.<br>`<List> the <files> from the <directory: "./src">.` | -| **Filter** | Enumeration | OWN | Selects items matching criteria.<br>`<Filter> the <active> from the <users> where status = "active".` | -| **Sort** | Enumeration | OWN | Orders items in a sequence.<br>`<Sort> the <users> by <name>.` | -| **Throw** | Error Handling | RESPONSE | Signals an exception or fault.<br>`<Throw> a <NotFound: error> for the <user>.` | -| **Start** | Execution Control | OWN | Begins a process or session.<br>`<Start> the <http-server> with <contract>.` | -| **Stop** | Execution Control | OWN | Ends a process or session.<br>`<Stop> the <http-server> with <application>.` | -| **Stat** | Inspection | REQUEST | Checks metadata or status of a resource.<br>`<Stat> the <info> for the <file: "./doc.pdf">.` | -| **Read** | I/O | REQUEST | Reads data from storage or stream.<br>`<Read> the <config> from the <file: "./config.json">.` | -| **Write** | I/O | RESPONSE | Writes data to storage or stream.<br>`<Write> the <data> to the <file: "./output.txt">.` | -| **Append** | I/O | RESPONSE | Adds data to end of existing resource.<br>`<Append> the <log-line> to the <file: "./app.log">.` | -| **Split** | Manipulation | OWN | Breaks a data sequence into parts.<br>`<Split> the <words> from the <sentence> by /\s+/.` | -| **Merge** | Manipulation | OWN | Combines multiple sequences into one.<br>`<Merge> the <existing-user> with <update-data>.` | -| **Log** | Monitoring | RESPONSE | Records informational/debug output.<br>`<Log> "Server started" to the <console>.` | -| **Create** | Mutation | OWN | Makes a new resource or object.<br>`<Create> the <user> with { name: "Alice" }.` | -| **Update** | Mutation | OWN | Modifies an existing resource or object.<br>`<Update> the <user> with <changes>.` | -| **Delete** | Mutation | EXPORT | Removes a resource or entry.<br>`<Delete> the <user> from the <users> where id = <id>.` | -| **Copy** | Mutation | OWN | Duplicates data from one location to another.<br>`<Copy> the <file: "./a.txt"> to the <destination: "./b.txt">.` | -| **Move** | Mutation | OWN | Transfers data or resources.<br>`<Move> the <file: "./old.txt"> to the <destination: "./new.txt">.` | -| **Store** | Persistence | EXPORT | Saves data persistently.<br>`<Store> the <user> into the <user-repository>.` | -| **Compute** | Processing | OWN | Performs calculation or algorithm.<br>`<Compute> the <total> from <price> * <quantity>.` | -| **Transform** | Processing | OWN | Converts data from one form to another.<br>`<Transform> the <dto> from the <entity>.` | -| **Map** | Processing | OWN | Applies a function across elements.<br>`<Map> the <names> from the <users: name>.` | -| **ParseHtml** | Processing | OWN | Extracts structured data from HTML. Specifiers: `links`, `content`, `text`, `markdown`.<br>`<ParseHtml> the <result: markdown> from the <html>.` | -| **Reduce** | Processing | OWN | Aggregates elements into a summary.<br>`<Reduce> the <total> from the <amounts> with sum.` | -| **Accept** | Protocol | OWN | Acknowledges or agrees to a connection/request.<br>`<Accept> the <order: placed>.` | -| **Exists** | Query | REQUEST | Tests whether a resource or value is present.<br>`<Exists> the <found> for the <file: "./config.json">.` | -| **Validate** | Verification | OWN | Checks correctness or conformance.<br>`<Validate> the <data> for the <schema>.` | -| **Compare** | Evaluation | OWN | Compares two values or structures.<br>`<Compare> the <hash> against the <stored-hash>.` | -| **Assert** | Verification | OWN | Checks that a condition holds true.<br>`<Assert> the <value> equals <expected>.` | +| **Send** | Communication | RESPONSE | Delivers data or message outward.<br>`Send "Hello" to the <connection>.` | +| **Receive** | Communication | REQUEST | Accepts incoming data or message from external source.<br>`Receive the <message> from the <event>.` | +| **Request** | Communication | REQUEST | Initiates a query or ask for data or service.<br>`Request the <data> from the <api-url>.` | +| **Listen** | Communication | OWN | Waits for incoming events or data.<br>`Listen on port 9000 as <socket-server>.` | +| **Connect** | Communication | OWN | Establishes a link between endpoints.<br>`Connect to <host: "localhost"> on port 5432 as <db>.` | +| **Close** | Communication | OWN | Terminates a connection or handle.<br>`Close the <database-connection>.` | +| **Keepalive** | Communication | OWN | Maintains an active connection.<br>`Keepalive the <application> for the <events>.` | +| **Notify** | Communication | RESPONSE | Signals a change or event to observers.<br>`Notify the <alert> to the <admin>.` | +| **Broadcast** | Communication | RESPONSE | Sends to multiple recipients.<br>`Broadcast the <message> to the <socket-server>.` | +| **Publish** | Communication | EXPORT | Publishes an event or message to a channel.<br>`Publish as <app-config> <config>.` | +| **Emit** | Communication | EXPORT | Emits an event or signal.<br>`Emit a <UserCreated: event> with <user>.` | +| **Make** | Construction | OWN | Builds or prepares a resource (e.g., dirs).<br>`Make the <output-dir> to the <path: "./output">.` | +| **Execute** | Control | OWN | Runs a command or code block.<br>`Execute the <result> for the <command: "ls"> with "-la".` | +| **Call** | Control | OWN | Invokes a function or service.<br>`Call the <result> via <API: POST /users> with <data>.` | +| **Return** | Control | RESPONSE | Sends back a result from a call.<br>`Return an <OK: status> with <data>.` | +| **Given** | Control/Spec | OWN | Denotes initial precondition in scenarios.<br>`Given the <user> with { name: "Test" }.` | +| **When** | Control/Spec | OWN | Denotes conditional trigger.<br>`When the <action> from the <feature-set>.` | +| **Then** | Control/Spec | OWN | Denotes expected result after condition.<br>`Then the <result> with <expected>.` | +| **Extract** | Data Access | REQUEST | Pulls a subset or component from a larger data structure. PascalCase qualifiers enable typed extraction with OpenAPI schema validation (ARO-0046).<br>`Extract the <user-id> from the <request: parameters>.`<br>`Extract the <data: UserEvent> from the <event: data>.` | +| **Retrieve** | Data Access | REQUEST | Gets existing data by key or identifier.<br>`Retrieve the <user> from the <user-repository> where id = <id>.` | +| **List** | Enumeration | REQUEST | Enumerates items in a collection or directory.<br>`List the <files> from the <directory: "./src">.` | +| **Filter** | Enumeration | OWN | Selects items matching criteria.<br>`Filter the <active> from the <users> where status = "active".` | +| **Sort** | Enumeration | OWN | Orders items in a sequence.<br>`Sort the <users> by <name>.` | +| **Throw** | Error Handling | RESPONSE | Signals an exception or fault.<br>`Throw a <NotFound: error> for the <user>.` | +| **Start** | Execution Control | OWN | Begins a process or session.<br>`Start the <http-server> with <contract>.` | +| **Stop** | Execution Control | OWN | Ends a process or session.<br>`Stop the <http-server> with <application>.` | +| **Stat** | Inspection | REQUEST | Checks metadata or status of a resource.<br>`Stat the <info> for the <file: "./doc.pdf">.` | +| **Read** | I/O | REQUEST | Reads data from storage or stream.<br>`Read the <config> from the <file: "./config.json">.` | +| **Write** | I/O | RESPONSE | Writes data to storage or stream.<br>`Write the <data> to the <file: "./output.txt">.` | +| **Append** | I/O | RESPONSE | Adds data to end of existing resource.<br>`Append the <log-line> to the <file: "./app.log">.` | +| **Split** | Manipulation | OWN | Breaks a data sequence into parts.<br>`Split the <words> from the <sentence> by /\s+/.` | +| **Merge** | Manipulation | OWN | Combines multiple sequences into one.<br>`Merge the <existing-user> with <update-data>.` | +| **Log** | Monitoring | RESPONSE | Records informational/debug output.<br>`Log "Server started" to the <console>.` | +| **Create** | Mutation | OWN | Makes a new resource or object.<br>`Create the <user> with { name: "Alice" }.` | +| **Update** | Mutation | OWN | Modifies an existing resource or object.<br>`Update the <user> with <changes>.` | +| **Delete** | Mutation | EXPORT | Removes a resource or entry.<br>`Delete the <user> from the <users> where id = <id>.` | +| **Copy** | Mutation | OWN | Duplicates data from one location to another.<br>`Copy the <file: "./a.txt"> to the <destination: "./b.txt">.` | +| **Move** | Mutation | OWN | Transfers data or resources.<br>`Move the <file: "./old.txt"> to the <destination: "./new.txt">.` | +| **Store** | Persistence | EXPORT | Saves data persistently.<br>`Store the <user> into the <user-repository>.` | +| **Compute** | Processing | OWN | Performs calculation or algorithm.<br>`Compute the <total> from <price> * <quantity>.` | +| **Transform** | Processing | OWN | Converts data from one form to another.<br>`Transform the <dto> from the <entity>.` | +| **Map** | Processing | OWN | Applies a function across elements.<br>`Map the <names> from the <users: name>.` | +| **ParseHtml** | Processing | OWN | Extracts structured data from HTML. Specifiers: `links`, `content`, `text`, `markdown`.<br>`ParseHtml the <result: markdown> from the <html>.` | +| **Reduce** | Processing | OWN | Aggregates elements into a summary.<br>`Reduce the <total> from the <amounts> with sum.` | +| **Accept** | Protocol | OWN | Acknowledges or agrees to a connection/request.<br>`Accept the <order: placed>.` | +| **Exists** | Query | REQUEST | Tests whether a resource or value is present.<br>`Exists the <found> for the <file: "./config.json">.` | +| **Validate** | Verification | OWN | Checks correctness or conformance.<br>`Validate the <data> for the <schema>.` | +| **Compare** | Evaluation | OWN | Compares two values or structures.<br>`Compare the <hash> against the <stored-hash>.` | +| **Assert** | Verification | OWN | Checks that a condition holds true.<br>`Assert the <value> equals <expected>.` | ## Summary by Semantic Role diff --git a/Book/TheConstructionStudies/AppendixB-Grammar.md b/Book/TheConstructionStudies/AppendixB-Grammar.md index be2aaf14..830947ef 100644 --- a/Book/TheConstructionStudies/AppendixB-Grammar.md +++ b/Book/TheConstructionStudies/AppendixB-Grammar.md @@ -251,7 +251,7 @@ program = feature_set ### ARO Statement Parse ``` -"<Extract> the <user-id> from the <request: parameters>." +"Extract the <user-id> from the <request: parameters>." = aro_statement = action , article , result , preposition , article , object , "." @@ -261,7 +261,7 @@ program = feature_set ### Guarded Statement Parse ``` -"<Return> a <NotFound: status> for the <user> when <user> is empty." +"Return a <NotFound: status> for the <user> when <user> is empty." = guarded_statement = aro_statement_base , "when" , condition , "." diff --git a/Book/TheConstructionStudies/Chapter01-DesignPhilosophy.md b/Book/TheConstructionStudies/Chapter01-DesignPhilosophy.md index 3b7b4e02..6deeb141 100644 --- a/Book/TheConstructionStudies/Chapter01-DesignPhilosophy.md +++ b/Book/TheConstructionStudies/Chapter01-DesignPhilosophy.md @@ -244,7 +244,7 @@ ARO's error handling is unusual: there is none. Programmers write only the succe ``` Statement: -<Retrieve> the <user> from the <user-repository> where id = <id>. +Retrieve the <user> from the <user-repository> where id = <id>. On failure, becomes: "Cannot retrieve the user from the user-repository where id = 530." diff --git a/Book/TheConstructionStudies/Chapter03-SyntacticAnalysis.md b/Book/TheConstructionStudies/Chapter03-SyntacticAnalysis.md index 3d18eb92..02024e78 100644 --- a/Book/TheConstructionStudies/Chapter03-SyntacticAnalysis.md +++ b/Book/TheConstructionStudies/Chapter03-SyntacticAnalysis.md @@ -273,7 +273,7 @@ private func parsePrecedence(_ minPrecedence: Precedence) throws -> any Expressi ## The AROStatement Parse -The core statement form is: `<Action> [article] <Result> preposition [article] <Object> [clauses] .` +The core statement form is: `Action [article] <Result> preposition [article] <Object> [clauses] .` ```swift // Parser.swift:197-350 (simplified) diff --git a/Book/TheConstructionStudies/Chapter04-AbstractSyntax.md b/Book/TheConstructionStudies/Chapter04-AbstractSyntax.md index 3f415229..57a25b5b 100644 --- a/Book/TheConstructionStudies/Chapter04-AbstractSyntax.md +++ b/Book/TheConstructionStudies/Chapter04-AbstractSyntax.md @@ -126,9 +126,9 @@ The five statement types: | Statement | Purpose | Example | |-----------|---------|---------| -| `AROStatement` | Core action-result-object | `<Extract> the <user> from the <request>.` | -| `PublishStatement` | Variable export | `<Publish> as <alias> <variable>.` | -| `RequireStatement` | Dependency declaration | `<Require> the <config> from the <environment>.` | +| `AROStatement` | Core action-result-object | `Extract the <user> from the <request>.` | +| `PublishStatement` | Variable export | `Publish as <alias> <variable>.` | +| `RequireStatement` | Dependency declaration | `Require the <config> from the <environment>.` | | `MatchStatement` | Pattern matching | `match <status> { case "active" { ... } }` | | `ForEachLoop` | Iteration | `for each <item> in <items> { ... }` | @@ -423,7 +423,7 @@ public struct SourceSpan: Sendable, Equatable { Spans propagate through parsing via `merged(with:)`: ```swift -// When parsing: <Extract> the <user> from the <request>. +// When parsing: Extract the <user> from the <request>. let startToken = try expect(.leftAngle, ...) // start location // ... parse contents ... let endToken = try expect(.dot, ...) // end location @@ -442,7 +442,7 @@ Spans enable precise error messages: Error: Cannot retrieve the user from the user-repository at line 5, columns 4-52 - 5 | <Retrieve> the <user> from the <user-repository>. + 5 | Retrieve the <user> from the <user-repository>. | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` @@ -497,13 +497,13 @@ public enum ValueSource: Sendable { case none // standard syntax case literal(LiteralValue) // with "string" case expression(any Expression) // from <x> * <y> - case sinkExpression(any Expression) // <Log> "msg" to <console> (ARO-0043) + case sinkExpression(any Expression) // Log "msg" to <console> (ARO-0043) } ``` The enum makes invalid states unrepresentable. A statement cannot have both a literal value and an expression—the type system enforces this. -**Sink Syntax (ARO-0043)**: The `sinkExpression` case handles statements like `<Log> "Hello" to the <console>` where the result position contains an expression rather than a variable binding. +**Sink Syntax (ARO-0043)**: The `sinkExpression` case handles statements like `Log "Hello" to the <console>` where the result position contains an expression rather than a variable binding. ### Query Modifiers @@ -519,7 +519,7 @@ public struct QueryModifiers: Sendable { These clauses work together for data pipeline operations (ARO-0018): ```aro -<Retrieve> the <total: sum> from the <orders> where status = "shipped". +Retrieve the <total: sum> from the <orders> where status = "shipped". ``` ### Range Modifiers @@ -535,8 +535,8 @@ public struct RangeModifiers: Sendable { Used by date range (ARO-0041) and set operations (ARO-0042): ```aro -<Generate> the <dates> from <start-date> to <end-date>. -<Compute> the <result: intersect> from <set-a> with <set-b>. +Generate the <dates> from <start-date> to <end-date>. +Compute the <result: intersect> from <set-a> with <set-b>. ``` ### Statement Guard @@ -551,7 +551,7 @@ public struct StatementGuard: Sendable { Used for state guards (ARO-0022) and conditional actions (ARO-0004): ```aro -<Send> the <notification> to the <user> when <user: subscribed> is true. +Send the <notification> to the <user> when <user: subscribed> is true. ``` ### Semantic Analyzer Validation diff --git a/Book/TheConstructionStudies/Chapter07-EventArchitecture.md b/Book/TheConstructionStudies/Chapter07-EventArchitecture.md index 46fcba69..7c4b48fa 100644 --- a/Book/TheConstructionStudies/Chapter07-EventArchitecture.md +++ b/Book/TheConstructionStudies/Chapter07-EventArchitecture.md @@ -214,9 +214,9 @@ Pattern: `{EventName} Handler` ```aro (Send Welcome Email: UserCreated Handler) { - <Extract> the <user> from the <event: user>. - <Send> the <welcome-email> to the <user: email>. - <Return> an <OK: status> for the <notification>. + Extract the <user> from the <event: user>. + Send the <welcome-email> to the <user: email>. + Return an <OK: status> for the <notification>. } ``` @@ -250,9 +250,9 @@ Pattern: `{repository-name} Observer` ```aro (Log User Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Log> "User ${<changeType>}" to the <console>. - <Return> an <OK: status> for the <logging>. + Extract the <changeType> from the <event: changeType>. + Log "User ${<changeType>}" to the <console>. + Return an <OK: status> for the <logging>. } ``` @@ -274,9 +274,9 @@ Pattern: `{description}: File Event Handler` ```aro (Handle Modified: File Event Handler) { - <Extract> the <path> from the <event: path>. - <Log> "File changed: ${<path>}" to the <console>. - <Return> an <OK: status> for the <notification>. + Extract the <path> from the <event: path>. + Log "File changed: ${<path>}" to the <console>. + Return an <OK: status> for the <notification>. } ``` @@ -291,9 +291,9 @@ Pattern: `{description}: Socket Event Handler` ```aro (Data Received: Socket Event Handler) { - <Extract> the <data> from the <packet: data>. - <Send> the <data> to the <packet: connectionId>. - <Return> an <OK: status> for the <echo>. + Extract the <data> from the <packet: data>. + Send the <data> to the <packet: connectionId>. + Return an <OK: status> for the <echo>. } ``` @@ -304,17 +304,17 @@ Pattern: `{fieldName} StateObserver` or `{fieldName} StateObserver<from_to_to>` ```aro (* Observe all transitions on 'status' field *) (Audit Changes: status StateObserver) { - <Extract> the <fromState> from the <transition: fromState>. - <Extract> the <toState> from the <transition: toState>. - <Log> "Status: ${<fromState>} → ${<toState>}" to the <console>. - <Return> an <OK: status> for the <audit>. + Extract the <fromState> from the <transition: fromState>. + Extract the <toState> from the <transition: toState>. + Log "Status: ${<fromState>} → ${<toState>}" to the <console>. + Return an <OK: status> for the <audit>. } (* Observe specific transition: draft → placed *) (Notify Placed: status StateObserver<draft_to_placed>) { - <Extract> the <order> from the <transition: entity>. - <Send> the <order-confirmation> to the <order: customerEmail>. - <Return> an <OK: status> for the <notification>. + Extract the <order> from the <transition: entity>. + Send the <order-confirmation> to the <order: customerEmail>. + Return an <OK: status> for the <notification>. } ``` diff --git a/Book/TheConstructionStudies/Chapter08-NativeCompilation.md b/Book/TheConstructionStudies/Chapter08-NativeCompilation.md index 3f49f16e..30af9905 100644 --- a/Book/TheConstructionStudies/Chapter08-NativeCompilation.md +++ b/Book/TheConstructionStudies/Chapter08-NativeCompilation.md @@ -330,7 +330,7 @@ For each ARO statement, the generator: 4. **Calls the action function** ```llvm -; <Log> "Hello, World!" to the <console>. +; Log "Hello, World!" to the <console>. s0: ; Bind literal to _literal_ call void @aro_variable_bind_string(ptr %ctx, ptr @.str._literal_, ptr @.str.hello) diff --git a/Book/TheConstructionStudies/Chapter10-CriticalAssessment.md b/Book/TheConstructionStudies/Chapter10-CriticalAssessment.md index 85b9ddf6..dd74f32a 100644 --- a/Book/TheConstructionStudies/Chapter10-CriticalAssessment.md +++ b/Book/TheConstructionStudies/Chapter10-CriticalAssessment.md @@ -10,7 +10,7 @@ This chapter provides an honest evaluation of ARO's design decisions—what work ### Uniform Syntax -ARO's rigid `<Action> the <Result> from the <Object>` structure enables simple tooling: +ARO's rigid `Action the <Result> from the <Object>` structure enables simple tooling: - **Parsing**: Every statement follows the same pattern - **Analysis**: Data flow is explicit in the syntax @@ -24,10 +24,10 @@ The constraint that seemed limiting during design has proven valuable in practic Sequential execution with explicit short-circuit points makes debugging straightforward: ```aro -<Extract> the <user> from the <request: body>. (* 1 *) -<Validate> the <user> with <schema>. (* 2 - might short-circuit *) -<Store> the <user> into the <user-repository>. (* 3 *) -<Return> an <OK: status> for the <creation>. (* 4 *) +Extract the <user> from the <request: body>. (* 1 *) +Validate the <user> with <schema>. (* 2 - might short-circuit *) +Store the <user> into the <user-repository>. (* 3 *) +Return an <OK: status> for the <creation>. (* 4 *) ``` When something fails, you know exactly which statement failed and why. @@ -47,8 +47,8 @@ No explicit wiring code; the EventBus handles all routing. The verbose syntax reads like prose: ```aro -<Extract> the <email> from the <user: profile: contact: email>. -<Send> the <welcome-message> to the <email>. +Extract the <email> from the <user: profile: contact: email>. +Send the <welcome-message> to the <email>. ``` Even non-programmers can follow the logic. @@ -151,14 +151,14 @@ let handlerFunc = unsafeBitCast(funcPtr, to: HandlerFunc.self) The idea: prepositions carry semantic meaning (from = source, to = destination, with = modification). ```aro -<Extract> the <data> from the <request>. (* from = source *) -<Send> the <message> to the <user>. (* to = destination *) -<Update> the <user> with <changes>. (* with = modification *) +Extract the <data> from the <request>. (* from = source *) +Send the <message> to the <user>. (* to = destination *) +Update the <user> with <changes>. (* with = modification *) ``` **The Problem**: Too subtle. Developers don't intuitively distinguish between: -- `<Store> the <user> into the <repository>.` -- `<Store> the <user> to the <repository>.` +- `Store the <user> into the <repository>.` +- `Store the <user> to the <repository>.` Both seem valid, but only one is correct. @@ -171,7 +171,7 @@ Both seem valid, but only one is correct. The idea: Types are inferred from usage and OpenAPI schemas. ```aro -<Extract> the <user> from the <request: body>. (* user type comes from OpenAPI *) +Extract the <user> from the <request: body>. (* user type comes from OpenAPI *) ``` **The Problem**: Tooling becomes harder: @@ -181,7 +181,7 @@ The idea: Types are inferred from usage and OpenAPI schemas. **What We'd Change**: Optional type annotations with inference as fallback: ```aro -<Extract> the <user: User> from the <request: body>. +Extract the <user: User> from the <request: body>. ``` --- diff --git a/Book/TheInteractiveDialog/Chapter01-Enter.md b/Book/TheInteractiveDialog/Chapter01-Enter.md index 0d72a916..4fa63eb2 100644 --- a/Book/TheInteractiveDialog/Chapter01-Enter.md +++ b/Book/TheInteractiveDialog/Chapter01-Enter.md @@ -43,7 +43,7 @@ ARO REPL Commands: :quit, :q, :exit Exit the REPL Type ARO statements directly, ending with . -Example: <Set> the <x> to 42. +Example: Set the <x> to 42. ``` Commands that start with `:` talk to the REPL itself. Everything else is ARO. diff --git a/Book/TheInteractiveDialog/Chapter02-Speak.md b/Book/TheInteractiveDialog/Chapter02-Speak.md index 923a14e7..681f77ca 100644 --- a/Book/TheInteractiveDialog/Chapter02-Speak.md +++ b/Book/TheInteractiveDialog/Chapter02-Speak.md @@ -9,7 +9,7 @@ Type this: ``` -aro> <Set> the <greeting> to "Hello, World". +aro> Set the <greeting> to "Hello, World". => OK ``` @@ -26,7 +26,7 @@ The `=> OK` confirms: the statement executed. The variable `greeting` now exists Want to see what you created? Log it: ``` -aro> <Log> <greeting> to the <console>. +aro> Log <greeting> to the <console>. Hello, World => OK ``` @@ -40,13 +40,13 @@ This is the power of the REPL: immediate feedback. No files. No compilation. You Try some arithmetic: ``` -aro> <Set> the <x> to 10. +aro> Set the <x> to 10. => OK -aro> <Set> the <y> to 20. +aro> Set the <y> to 20. => OK -aro> <Compute> the <sum> from <x> + <y>. +aro> Compute the <sum> from <x> + <y>. => 30 ``` @@ -71,7 +71,7 @@ The REPL can evaluate bare expressions too. No action needed. Make a mistake. It's safe here. ``` -aro> <Compute> the <result> from <undefined> + 1. +aro> Compute the <result> from <undefined> + 1. Error: Undefined variable 'undefined' Suggestion: Use :vars to see available variables @@ -95,14 +95,14 @@ The REPL is patient. It corrects. It waits for you to try again. Every statement ends with a period. It's ARO's way of knowing you're done: ``` -aro> <Set> the <name> to "Alice". +aro> Set the <name> to "Alice". => OK ``` Forget the period and press Enter? The REPL waits for more: ``` -aro> <Set> the <name> to "Alice" +aro> Set the <name> to "Alice" ...> . => OK ``` diff --git a/Book/TheInteractiveDialog/Chapter03-Remember.md b/Book/TheInteractiveDialog/Chapter03-Remember.md index fa047674..643c25bd 100644 --- a/Book/TheInteractiveDialog/Chapter03-Remember.md +++ b/Book/TheInteractiveDialog/Chapter03-Remember.md @@ -9,13 +9,13 @@ Variables don't disappear between statements. The session remembers: ``` -aro> <Set> the <x> to 10. +aro> Set the <x> to 10. => OK -aro> <Set> the <y> to 20. +aro> Set the <y> to 20. => OK -aro> <Compute> the <sum> from <x> + <y>. +aro> Compute the <sum> from <x> + <y>. => 30 ``` @@ -43,7 +43,7 @@ A table of your world. Every variable, its type, its value. For complex objects, inspect them individually: ``` -aro> <Create> the <user> with { name: "Alice", age: 30 }. +aro> Create the <user> with { name: "Alice", age: 30 }. => { name: "Alice", age: 30 } aro> :vars user @@ -73,13 +73,13 @@ The structure revealed. The REPL is perfect for building complexity gradually: ``` -aro> <Set> the <base-price> to 100. +aro> Set the <base-price> to 100. => OK -aro> <Compute> the <tax> from <base-price> * 0.2. +aro> Compute the <tax> from <base-price> * 0.2. => 20 -aro> <Compute> the <total> from <base-price> + <tax>. +aro> Compute the <total> from <base-price> + <tax>. => 120 aro> :vars diff --git a/Book/TheInteractiveDialog/Chapter04-Define.md b/Book/TheInteractiveDialog/Chapter04-Define.md index 230f6f18..1d7af841 100644 --- a/Book/TheInteractiveDialog/Chapter04-Define.md +++ b/Book/TheInteractiveDialog/Chapter04-Define.md @@ -10,10 +10,10 @@ ARO programs are made of feature sets—groups of statements that work together. ```aro (Calculate Area: Geometry) { - <Extract> the <width> from the <input: width>. - <Extract> the <height> from the <input: height>. - <Compute> the <area> from <width> * <height>. - <Return> an <OK: status> with { area: <area> }. + Extract the <width> from the <input: width>. + Extract the <height> from the <input: height>. + Compute the <area> from <width> * <height>. + Return an <OK: status> with { area: <area> }. } ``` @@ -31,13 +31,13 @@ aro> (Calculate Area: Geometry) { The prompt changes. You're now inside the feature set. Each statement you type becomes part of it: ``` -(Calculate Area)> <Extract> the <width> from the <input: width>. +(Calculate Area)> Extract the <width> from the <input: width>. + -(Calculate Area)> <Extract> the <height> from the <input: height>. +(Calculate Area)> Extract the <height> from the <input: height>. + -(Calculate Area)> <Compute> the <area> from <width> * <height>. +(Calculate Area)> Compute the <area> from <width> * <height>. + -(Calculate Area)> <Return> an <OK: status> with { area: <area> }. +(Calculate Area)> Return an <OK: status> with { area: <area> }. + ``` @@ -88,7 +88,7 @@ aro> :invoke Calculate Area { width: 3, height: 4 } Feature sets aren't the only multi-line construct. Objects work too: ``` -aro> <Create> the <config> with { +aro> Create the <config> with { ...> host: "localhost", ...> port: 8080, ...> debug: true diff --git a/Book/TheInteractiveDialog/Chapter05-Command.md b/Book/TheInteractiveDialog/Chapter05-Command.md index 01d7b1dc..cc459cf0 100644 --- a/Book/TheInteractiveDialog/Chapter05-Command.md +++ b/Book/TheInteractiveDialog/Chapter05-Command.md @@ -71,7 +71,7 @@ Press `Tab` for intelligent completion: ``` aro> <Com[TAB] -<Compute> <Compare> <Connect> +Compute Compare <Connect> aro> :h[TAB] :help :history @@ -85,11 +85,11 @@ See what you've done: ``` aro> :history 5 -1. [ok] <Set> the <x> to 10. 2ms -2. [ok] <Set> the <y> to 20. 1ms -3. [ok] <Compute> the <sum> from... 3ms -4. [err] <Get> the <missing> from... -- -5. [ok] <Log> "test" to <console>. 1ms +1. [ok] Set the <x> to 10. 2ms +2. [ok] Set the <y> to 20. 1ms +3. [ok] Compute the <sum> from... 3ms +4. [err] Get the <missing> from... -- +5. [ok] Log "test" to <console>. 1ms ``` Status, statement, timing. A record of your conversation. diff --git a/Book/TheInteractiveDialog/Chapter06-Extend.md b/Book/TheInteractiveDialog/Chapter06-Extend.md index ee4ec3c1..b4852ff7 100644 --- a/Book/TheInteractiveDialog/Chapter06-Extend.md +++ b/Book/TheInteractiveDialog/Chapter06-Extend.md @@ -26,7 +26,7 @@ That's it. A server is running. Now define handlers: ``` aro> (healthCheck: API) { -(healthCheck)> <Return> an <OK: status> with { status: "healthy" }. +(healthCheck)> Return an <OK: status> with { status: "healthy" }. (healthCheck)> } Feature set 'healthCheck' defined ``` @@ -73,7 +73,7 @@ Plugin loaded successfully Now use them: ``` -aro> <Set> the <data> to { name: "test", valid: true }. +aro> Set the <data> to { name: "test", valid: true }. => OK aro> <Validate-json> the <result> from the <data>. @@ -118,8 +118,8 @@ aro> :service start file-watcher --path ./data File watcher started on ./data aro> (File Handler: File Event Handler) { -(File Handler)> <Extract> the <path> from the <event: path>. -(File Handler)> <Log> "Changed: ${<path>}" to the <console>. +(File Handler)> Extract the <path> from the <event: path>. +(File Handler)> Log "Changed: ${<path>}" to the <console>. (File Handler)> } Feature set registered for file events ``` diff --git a/Book/TheInteractiveDialog/Chapter07-Depart.md b/Book/TheInteractiveDialog/Chapter07-Depart.md index 23f7b0ab..164c23cc 100644 --- a/Book/TheInteractiveDialog/Chapter07-Depart.md +++ b/Book/TheInteractiveDialog/Chapter07-Depart.md @@ -13,13 +13,13 @@ Every statement you've typed, every variable you've created, every feature set y The `:export` command captures your session as a proper `.aro` file: ``` -aro> <Set> the <base-price> to 100. +aro> Set the <base-price> to 100. => OK -aro> <Compute> the <tax> from <base-price> * 0.2. +aro> Compute the <tax> from <base-price> * 0.2. => 20 -aro> <Compute> the <total> from <base-price> + <tax>. +aro> Compute the <total> from <base-price> + <tax>. => 120 aro> :export @@ -27,9 +27,9 @@ aro> :export (* Date: 2026-02-14T10:30:00Z *) (REPL Session: Interactive) { - <Set> the <base-price> to 100. - <Compute> the <tax> from <base-price> * 0.2. - <Compute> the <total> from <base-price> + <tax>. + Set the <base-price> to 100. + Compute the <tax> from <base-price> * 0.2. + Compute the <total> from <base-price> + <tax>. } ``` @@ -59,14 +59,14 @@ The result: (* Generated test from ARO REPL session *) (Pricing Test: Test) { - <Set> the <base-price> to 100. - <Assert> the <base-price> is 100. + Set the <base-price> to 100. + Assert the <base-price> is 100. - <Compute> the <tax> from <base-price> * 0.2. - <Assert> the <tax> is 20. + Compute the <tax> from <base-price> * 0.2. + Assert the <tax> is 20. - <Compute> the <total> from <base-price> + <tax>. - <Assert> the <total> is 120. + Compute the <total> from <base-price> + <tax>. + Assert the <total> is 120. } ``` diff --git a/Book/TheLanguageGuide/AppendixA-ActionReference.md b/Book/TheLanguageGuide/AppendixA-ActionReference.md index 208b9e62..754ed127 100644 --- a/Book/TheLanguageGuide/AppendixA-ActionReference.md +++ b/Book/TheLanguageGuide/AppendixA-ActionReference.md @@ -6,54 +6,54 @@ Complete reference for all built-in actions in ARO. | Action | Role | Description | Example | |--------|------|-------------|---------| -| **Extract** | REQUEST | Pull data from structured source | `<Extract> the <id> from the <request: params>.` | -| **Retrieve** | REQUEST | Fetch from repository | `<Retrieve> the <user> from the <users> where id = <id>.` | -| **Request** | REQUEST | Make HTTP request | `<Request> the <data> from the <api-url>.` | -| **Read** | REQUEST | Read from file | `<Read> the <config> from the <file: "./config.json">.` | -| **List** | REQUEST | List directory contents | `<List> the <files> from the <directory: src-path>.` | -| **Stat** | REQUEST | Get file metadata | `<Stat> the <info> for the <file: "./doc.pdf">.` | -| **Exists** | REQUEST | Check file existence | `<Exists> the <found> for the <file: "./config.json">.` | -| **Receive** | REQUEST | Receive event data | `<Receive> the <message> from the <event>.` | -| **Execute** | REQUEST | Execute shell command | `<Execute> the <result> for the <command: "ls"> with "-la".` | -| **Create** | OWN | Create new data | `<Create> the <user> with { name: "Alice" }.` | -| **Compute** | OWN | Perform calculations | `<Compute> the <total> for the <items>.` | -| **Transform** | OWN | Convert/map data | `<Transform> the <dto> from the <entity>.` | -| **Validate** | OWN | Check against rules | `<Validate> the <data> for the <schema>.` | -| **Compare** | OWN | Compare values | `<Compare> the <hash> against the <stored>.` | -| **Update** | OWN | Modify existing data | `<Update> the <user> with <changes>.` | -| **Make** | OWN | Create directory | `<Make> the <dir> to the <path: "./out">.` | -| **Copy** | OWN | Copy file/directory | `<Copy> the <file: "./a.txt"> to the <destination: "./b.txt">.` | -| **Move** | OWN | Move/rename file | `<Move> the <file: "./old.txt"> to the <destination: "./new.txt">.` | -| **Map** | OWN | Transform collection elements | `<Map> the <names> from the <users: name>.` | -| **Filter** | OWN | Select matching elements | `<Filter> the <active> from the <users> where status = "active".` | -| **Reduce** | OWN | Aggregate collection | `<Reduce> the <total> from the <items> with sum(<amount>).` | -| **Sort** | OWN | Order collection | `<Sort> the <users> by <name>.` | -| **Split** | OWN | Split string by regex | `<Split> the <parts> from the <string> by /,/.` | -| **Merge** | OWN | Combine data | `<Merge> the <existing-user> with <update-data>.` | -| **Return** | RESPONSE | Return result | `<Return> an <OK: status> with <data>.` | -| **Throw** | RESPONSE | Throw error | `<Throw> a <NotFound: error> for the <user>.` | -| **Log** | EXPORT | Write to logs | `<Log> "Done" to the <console>.` | -| **Store** | EXPORT | Save to repository | `<Store> the <user> into the <users>.` | -| **Write** | EXPORT | Write to file | `<Write> the <data> to the <file: "./out.txt">.` | -| **Append** | EXPORT | Append to file | `<Append> the <line> to the <file: "./log.txt">.` | -| **Send** | EXPORT | Send to destination | `<Send> the <email> to the <recipient>.` | -| **Emit** | EXPORT | Emit domain event | `<Emit> a <UserCreated: event> with <user>.` | -| **Publish** | EXPORT | Make globally available | `<Publish> as <config> <settings>.` | -| **Notify** | EXPORT | Send notification | `<Notify> the <alert> to the <admin>.` | -| **Delete** | EXPORT | Remove data | `<Delete> the <user> from the <users> where id = <id>.` | -| **Start** | SERVICE | Start a service | `<Start> the <http-server> with <contract>.` | -| **Stop** | SERVICE | Stop a service | `<Stop> the <http-server> with <application>.` | -| **Listen** | SERVICE | Listen for connections | `<Listen> on port 9000 as <socket-server>.` | -| **Connect** | SERVICE | Connect to service | `<Connect> to <host: "db"> on port 5432.` | -| **Close** | SERVICE | Close connection | `<Close> the <connection>.` | -| **Broadcast** | SERVICE | Send to all connections | `<Broadcast> the <msg> to the <server>.` | -| **Keepalive** | SERVICE | Keep app running | `<Keepalive> the <app> for the <events>.` | -| **Call** | SERVICE | Call external API | `<Call> the <result> via <API: POST /users>.` | -| **Accept** | STATE | Accept state transition | `<Accept> the <order: placed>.` | -| **Given** | TEST | Test precondition | `<Given> the <user> with { name: "Test" }.` | -| **When** | TEST | Test action | `<When> the <action> is performed.` | -| **Then** | TEST | Test expectation | `<Then> the <result> should be <expected>.` | -| **Assert** | TEST | Assert condition | `<Assert> the <value> equals <expected>.` | +| **Extract** | REQUEST | Pull data from structured source | `Extract the <id> from the <request: params>.` | +| **Retrieve** | REQUEST | Fetch from repository | `Retrieve the <user> from the <users> where id = <id>.` | +| **Request** | REQUEST | Make HTTP request | `Request the <data> from the <api-url>.` | +| **Read** | REQUEST | Read from file | `Read the <config> from the <file: "./config.json">.` | +| **List** | REQUEST | List directory contents | `List the <files> from the <directory: src-path>.` | +| **Stat** | REQUEST | Get file metadata | `Stat the <info> for the <file: "./doc.pdf">.` | +| **Exists** | REQUEST | Check file existence | `Exists the <found> for the <file: "./config.json">.` | +| **Receive** | REQUEST | Receive event data | `Receive the <message> from the <event>.` | +| **Execute** | REQUEST | Execute shell command | `Execute the <result> for the <command: "ls"> with "-la".` | +| **Create** | OWN | Create new data | `Create the <user> with { name: "Alice" }.` | +| **Compute** | OWN | Perform calculations | `Compute the <total> for the <items>.` | +| **Transform** | OWN | Convert/map data | `Transform the <dto> from the <entity>.` | +| **Validate** | OWN | Check against rules | `Validate the <data> for the <schema>.` | +| **Compare** | OWN | Compare values | `Compare the <hash> against the <stored>.` | +| **Update** | OWN | Modify existing data | `Update the <user> with <changes>.` | +| **Make** | OWN | Create directory | `Make the <dir> to the <path: "./out">.` | +| **Copy** | OWN | Copy file/directory | `Copy the <file: "./a.txt"> to the <destination: "./b.txt">.` | +| **Move** | OWN | Move/rename file | `Move the <file: "./old.txt"> to the <destination: "./new.txt">.` | +| **Map** | OWN | Transform collection elements | `Map the <names> from the <users: name>.` | +| **Filter** | OWN | Select matching elements | `Filter the <active> from the <users> where status = "active".` | +| **Reduce** | OWN | Aggregate collection | `Reduce the <total> from the <items> with sum(<amount>).` | +| **Sort** | OWN | Order collection | `Sort the <users> by <name>.` | +| **Split** | OWN | Split string by regex | `Split the <parts> from the <string> by /,/.` | +| **Merge** | OWN | Combine data | `Merge the <existing-user> with <update-data>.` | +| **Return** | RESPONSE | Return result | `Return an <OK: status> with <data>.` | +| **Throw** | RESPONSE | Throw error | `Throw a <NotFound: error> for the <user>.` | +| **Log** | EXPORT | Write to logs | `Log "Done" to the <console>.` | +| **Store** | EXPORT | Save to repository | `Store the <user> into the <users>.` | +| **Write** | EXPORT | Write to file | `Write the <data> to the <file: "./out.txt">.` | +| **Append** | EXPORT | Append to file | `Append the <line> to the <file: "./log.txt">.` | +| **Send** | EXPORT | Send to destination | `Send the <email> to the <recipient>.` | +| **Emit** | EXPORT | Emit domain event | `Emit a <UserCreated: event> with <user>.` | +| **Publish** | EXPORT | Make globally available | `Publish as <config> <settings>.` | +| **Notify** | EXPORT | Send notification | `Notify the <alert> to the <admin>.` | +| **Delete** | EXPORT | Remove data | `Delete the <user> from the <users> where id = <id>.` | +| **Start** | SERVICE | Start a service | `Start the <http-server> with <contract>.` | +| **Stop** | SERVICE | Stop a service | `Stop the <http-server> with <application>.` | +| **Listen** | SERVICE | Listen for connections | `Listen on port 9000 as <socket-server>.` | +| **Connect** | SERVICE | Connect to service | `Connect to <host: "db"> on port 5432.` | +| **Close** | SERVICE | Close connection | `Close the <connection>.` | +| **Broadcast** | SERVICE | Send to all connections | `Broadcast the <msg> to the <server>.` | +| **Keepalive** | SERVICE | Keep app running | `Keepalive the <app> for the <events>.` | +| **Call** | SERVICE | Call external API | `Call the <result> via <API: POST /users>.` | +| **Accept** | STATE | Accept state transition | `Accept the <order: placed>.` | +| **Given** | TEST | Test precondition | `Given the <user> with { name: "Test" }.` | +| **When** | TEST | Test action | `When the <action> is performed.` | +| **Then** | TEST | Test expectation | `Then the <result> should be <expected>.` | +| **Assert** | TEST | Assert condition | `Assert the <value> equals <expected>.` | ## Action Categories @@ -77,17 +77,17 @@ Pulls data from a structured source. **Syntax:** ```aro -<Extract> the <result> from the <source: property>. -<Extract> the <result: specifier> from the <list>. +Extract the <result> from the <source: property>. +Extract the <result: specifier> from the <list>. ``` **Examples:** ```aro -<Extract> the <user-id> from the <request: parameters>. -<Extract> the <body> from the <request: body>. -<Extract> the <token> from the <request: headers.Authorization>. -<Extract> the <email> from the <user: email>. -<Extract> the <order> from the <event: order>. +Extract the <user-id> from the <request: parameters>. +Extract the <body> from the <request: body>. +Extract the <token> from the <request: headers.Authorization>. +Extract the <email> from the <user: email>. +Extract the <order> from the <event: order>. ``` **List Element Access (ARO-0038):** @@ -96,18 +96,18 @@ Extract specific elements from arrays using result specifiers: ```aro (* Keywords *) -<Extract> the <item: first> from the <list>. -<Extract> the <item: last> from the <list>. +Extract the <item: first> from the <list>. +Extract the <item: last> from the <list>. (* Numeric index: 0 = last, 1 = second-to-last *) -<Extract> the <item: 0> from the <list>. -<Extract> the <item: 1> from the <list>. +Extract the <item: 0> from the <list>. +Extract the <item: 1> from the <list>. (* Range: elements 2, 3, 4, 5 *) -<Extract> the <subset: 2-5> from the <list>. +Extract the <subset: 2-5> from the <list>. (* Pick: elements at indices 0, 3, 7 *) -<Extract> the <selection: 0,3,7> from the <list>. +Extract the <selection: 0,3,7> from the <list>. ``` | Specifier | Returns | @@ -129,15 +129,15 @@ Fetches data from a repository. **Syntax:** ```aro -<Retrieve> the <result> from the <repository> [where <condition>]. +Retrieve the <result> from the <repository> [where <condition>]. ``` **Examples:** ```aro -<Retrieve> the <user> from the <user-repository>. -<Retrieve> the <user> from the <user-repository> where id = <user-id>. -<Retrieve> the <orders> from the <order-repository> where status = "pending". -<Retrieve> the <products> from the <repository> where category = <cat> and active = true. +Retrieve the <user> from the <user-repository>. +Retrieve the <user> from the <user-repository> where id = <user-id>. +Retrieve the <orders> from the <order-repository> where status = "pending". +Retrieve the <products> from the <repository> where category = <cat> and active = true. ``` **Valid Prepositions:** `from` @@ -150,24 +150,24 @@ Makes HTTP requests to external URLs or APIs. **Syntax:** ```aro -<Request> the <result> from <url>. (* GET request *) -<Request> the <result> to <url> with <data>. (* POST request *) -<Request> the <result> via METHOD <url>. (* Explicit method *) +Request the <result> from <url>. (* GET request *) +Request the <result> to <url> with <data>. (* POST request *) +Request the <result> via METHOD <url>. (* Explicit method *) ``` **Examples:** ```aro (* GET request *) -<Create> the <api-url> with "https://api.open-meteo.com/v1/forecast". -<Request> the <weather> from the <api-url>. +Create the <api-url> with "https://api.open-meteo.com/v1/forecast". +Request the <weather> from the <api-url>. (* POST request *) -<Create> the <user-data> with { name: "Alice", email: "alice@example.com" }. -<Request> the <result> to the <api-url> with <user-data>. +Create the <user-data> with { name: "Alice", email: "alice@example.com" }. +Request the <result> to the <api-url> with <user-data>. (* PUT/DELETE/PATCH via explicit method *) -<Request> the <result> via PUT the <url> with <update-data>. -<Request> the <result> via DELETE the <url>. +Request the <result> via PUT the <url> with <update-data>. +Request the <result> via DELETE the <url>. ``` **Response Metadata:** @@ -187,15 +187,15 @@ Reads from files. **Syntax:** ```aro -<Read> the <result> from the <file: path>. -<Read> the <result: type> from the <file: path>. +Read the <result> from the <file: path>. +Read the <result: type> from the <file: path>. ``` **Examples:** ```aro -<Read> the <content> from the <file: "./data.txt">. -<Read> the <config: JSON> from the <file: "./config.json">. -<Read> the <image: bytes> from the <file: "./logo.png">. +Read the <content> from the <file: "./data.txt">. +Read the <config: JSON> from the <file: "./config.json">. +Read the <image: bytes> from the <file: "./logo.png">. ``` **Valid Prepositions:** `from` @@ -209,16 +209,16 @@ Executes shell commands on the host system and returns structured results. **Syntax:** ```aro (* Preferred: command in object specifier *) -<Execute> the <result> for the <command: "uptime">. -<Execute> the <result> for the <command: "ls"> with "-la". -<Execute> the <result> for the <command: "ls"> with ["-l", "-a", "-h"]. +Execute the <result> for the <command: "uptime">. +Execute the <result> for the <command: "ls"> with "-la". +Execute the <result> for the <command: "ls"> with ["-l", "-a", "-h"]. (* Legacy: full command in with clause *) -<Execute> the <result> for the <command> with "ls -la". -<Execute> the <result> for the <command> with <variable>. +Execute the <result> for the <command> with "ls -la". +Execute the <result> for the <command> with <variable>. (* Configuration object *) -<Execute> the <result> on the <system> with { +Execute the <result> on the <system> with { command: "command-string", workingDirectory: "/path", timeout: 30000 @@ -236,20 +236,20 @@ The Execute action returns a structured result with the following fields: **Examples:** ```aro (* Preferred syntax *) -<Execute> the <listing> for the <command: "ls"> with "-la". -<Return> an <OK: status> for the <listing>. +Execute the <listing> for the <command: "ls"> with "-la". +Return an <OK: status> for the <listing>. (* With error handling *) -<Execute> the <result> for the <command: "df"> with "-h". -<Log> <result.message> to the <console> when <result.error> = true. -<Return> an <Error: status> for the <result> when <result.error> = true. -<Return> an <OK: status> for the <result>. +Execute the <result> for the <command: "df"> with "-h". +Log <result.message> to the <console> when <result.error> = true. +Return an <Error: status> for the <result> when <result.error> = true. +Return an <OK: status> for the <result>. (* Using array for multiple arguments *) -<Execute> the <processes> for the <command: "ps"> with ["aux"]. +Execute the <processes> for the <command: "ps"> with ["aux"]. (* With configuration options *) -<Execute> the <result> on the <system> with { +Execute the <result> on the <system> with { command: "npm install", workingDirectory: "/app", timeout: 60000 @@ -279,14 +279,14 @@ Creates new data structures. **Syntax:** ```aro -<Create> the <result> with <data>. +Create the <result> with <data>. ``` **Examples:** ```aro -<Create> the <user> with <user-data>. -<Create> the <response> with { message: "Success" }. -<Create> the <order> with { +Create the <user> with <user-data>. +Create the <response> with { message: "Success" }. +Create the <order> with { items: <items>, total: <total>, customer: <customer-id> @@ -303,38 +303,38 @@ Performs calculations and transformations. **Syntax:** ```aro -<Compute> the <result> for the <input>. -<Compute> the <result> from <expression>. -<Compute> the <result: operation> from <input>. -<Compute> the <result: operation> from <input> with <second-input>. +Compute the <result> for the <input>. +Compute the <result> from <expression>. +Compute the <result: operation> from <input>. +Compute the <result: operation> from <input> with <second-input>. ``` **Built-in Operations:** | Operation | Description | Example | |-----------|-------------|---------| -| `length`, `count` | Count elements | `<Compute> the <len: length> from <text>.` | -| `uppercase` | Convert to UPPERCASE | `<Compute> the <upper: uppercase> from <text>.` | -| `lowercase` | Convert to lowercase | `<Compute> the <lower: lowercase> from <text>.` | -| `hash` | Compute hash value | `<Compute> the <h: hash> from <password>.` | -| `intersect` | Find common elements | `<Compute> the <common: intersect> from <a> with <b>.` | -| `difference` | Find elements in A not in B | `<Compute> the <diff: difference> from <a> with <b>.` | -| `union` | Combine all unique elements | `<Compute> the <all: union> from <a> with <b>.` | +| `length`, `count` | Count elements | `Compute the <len: length> from <text>.` | +| `uppercase` | Convert to UPPERCASE | `Compute the <upper: uppercase> from <text>.` | +| `lowercase` | Convert to lowercase | `Compute the <lower: lowercase> from <text>.` | +| `hash` | Compute hash value | `Compute the <h: hash> from <password>.` | +| `intersect` | Find common elements | `Compute the <common: intersect> from <a> with <b>.` | +| `difference` | Find elements in A not in B | `Compute the <diff: difference> from <a> with <b>.` | +| `union` | Combine all unique elements | `Compute the <all: union> from <a> with <b>.` | **Examples:** ```aro (* Basic computations *) -<Compute> the <total> for the <items>. -<Compute> the <hash> for the <password>. -<Compute> the <sum> from <a> + <b>. +Compute the <total> for the <items>. +Compute the <hash> for the <password>. +Compute the <sum> from <a> + <b>. (* Set operations *) -<Create> the <list-a> with [2, 3, 5]. -<Create> the <list-b> with [1, 2, 3, 4]. -<Compute> the <common: intersect> from <list-a> with <list-b>. +Create the <list-a> with [2, 3, 5]. +Create the <list-b> with [1, 2, 3, 4]. +Compute the <common: intersect> from <list-a> with <list-b>. (* Result: [2, 3] *) -<Compute> the <only-in-a: difference> from <list-a> with <list-b>. +Compute the <only-in-a: difference> from <list-a> with <list-b>. (* Result: [5] *) ``` @@ -348,15 +348,15 @@ Converts or maps data. **Syntax:** ```aro -<Transform> the <result> from the <source>. -<Transform> the <result> from the <source> with <modifications>. +Transform the <result> from the <source>. +Transform the <result> from the <source> with <modifications>. ``` **Examples:** ```aro -<Transform> the <dto> from the <entity>. -<Transform> the <updated-user> from the <user> with <updates>. -<Transform> the <response> from the <data>. +Transform the <dto> from the <entity>. +Transform the <updated-user> from the <user> with <updates>. +Transform the <response> from the <data>. ``` **Valid Prepositions:** `from` @@ -369,14 +369,14 @@ Checks data against rules. **Syntax:** ```aro -<Validate> the <data> for the <schema>. +Validate the <data> for the <schema>. ``` **Examples:** ```aro -<Validate> the <user-data> for the <user-schema>. -<Validate> the <email> for the <email-pattern>. -<Validate> the <order> for the <order-rules>. +Validate the <user-data> for the <user-schema>. +Validate the <email> for the <email-pattern>. +Validate the <order> for the <order-rules>. ``` **Valid Prepositions:** `for` @@ -389,13 +389,13 @@ Compares two values. **Syntax:** ```aro -<Compare> the <value1> against the <value2>. +Compare the <value1> against the <value2>. ``` **Examples:** ```aro -<Compare> the <password-hash> against the <stored-hash>. -<Compare> the <signature> against the <expected>. +Compare the <password-hash> against the <stored-hash>. +Compare the <signature> against the <expected>. ``` **Valid Prepositions:** `against` @@ -408,24 +408,24 @@ Splits a string into an array of parts using a regex delimiter. **Syntax:** ```aro -<Split> the <parts> from the <string> by /delimiter/. +Split the <parts> from the <string> by /delimiter/. ``` **Examples:** ```aro (* Split CSV line by comma *) -<Create> the <csv-line> with "apple,banana,cherry". -<Split> the <fruits> from the <csv-line> by /,/. +Create the <csv-line> with "apple,banana,cherry". +Split the <fruits> from the <csv-line> by /,/. (* fruits = ["apple", "banana", "cherry"] *) (* Split by whitespace *) -<Split> the <words> from the <sentence> by /\s+/. +Split the <words> from the <sentence> by /\s+/. (* Split by multiple delimiters *) -<Split> the <tokens> from the <code> by /[;,\s]+/. +Split the <tokens> from the <code> by /[;,\s]+/. (* Case-insensitive split *) -<Split> the <sections> from the <text> by /SECTION/i. +Split the <sections> from the <text> by /SECTION/i. ``` **Behavior:** @@ -444,26 +444,26 @@ Combines two data structures together. The source values are merged into the tar **Syntax:** ```aro -<Merge> the <target> with <source>. -<Merge> the <target> from <source>. +Merge the <target> with <source>. +Merge the <target> from <source>. ``` **Examples:** ```aro (* Merge update data into existing entity *) -<Retrieve> the <existing-user> from the <user-repository> where id = <id>. -<Extract> the <update-data> from the <request: body>. -<Merge> the <existing-user> with <update-data>. -<Store> the <existing-user> into the <user-repository>. +Retrieve the <existing-user> from the <user-repository> where id = <id>. +Extract the <update-data> from the <request: body>. +Merge the <existing-user> with <update-data>. +Store the <existing-user> into the <user-repository>. (* Combine configuration objects *) -<Merge> the <defaults> with <overrides>. +Merge the <defaults> with <overrides>. (* Concatenate arrays *) -<Merge> the <all-items> with <new-items>. +Merge the <all-items> with <new-items>. (* Concatenate strings *) -<Merge> the <greeting> with <name>. +Merge the <greeting> with <name>. ``` **Supported Types:** @@ -483,16 +483,16 @@ Returns a result with status. **Syntax:** ```aro -<Return> [article] <status> [with <data>] [for <context>]. +Return [article] <status> [with <data>] [for <context>]. ``` **Examples:** ```aro -<Return> an <OK: status> with <data>. -<Return> a <Created: status> with <resource>. -<Return> a <NoContent: status> for the <deletion>. -<Return> a <BadRequest: status> with <errors>. -<Return> a <NotFound: status> for the <missing: user>. +Return an <OK: status> with <data>. +Return a <Created: status> with <resource>. +Return a <NoContent: status> for the <deletion>. +Return a <BadRequest: status> with <errors>. +Return a <NotFound: status> for the <missing: user>. ``` **Valid Prepositions:** `with`, `for` @@ -505,14 +505,14 @@ Throws an error. **Syntax:** ```aro -<Throw> [article] <error-type> for the <context>. +Throw [article] <error-type> for the <context>. ``` **Examples:** ```aro -<Throw> a <ValidationError> for the <invalid: input>. -<Throw> a <NotFoundError> for the <missing: user>. -<Throw> an <AuthenticationError> for the <invalid: token>. +Throw a <ValidationError> for the <invalid: input>. +Throw a <NotFoundError> for the <missing: user>. +Throw an <AuthenticationError> for the <invalid: token>. ``` **Valid Prepositions:** `for` @@ -527,13 +527,13 @@ Saves to a repository. Triggers repository observers for new entries and updates **Syntax:** ```aro -<Store> the <data> into the <repository>. +Store the <data> into the <repository>. ``` **Examples:** ```aro -<Store> the <user> into the <user-repository>. -<Store> the <order> into the <order-repository>. +Store the <user> into the <user-repository>. +Store the <order> into the <order-repository>. ``` **Behavior:** @@ -554,13 +554,13 @@ Makes variables globally available. **Syntax:** ```aro -<Publish> as <alias> <variable>. +Publish as <alias> <variable>. ``` **Examples:** ```aro -<Publish> as <app-config> <config>. -<Publish> as <current-user> <user>. +Publish as <app-config> <config>. +Publish as <current-user> <user>. ``` **Valid Prepositions:** `as` @@ -577,10 +577,10 @@ Outputs messages to console (stdout or stderr). **Syntax:** ```aro -<Log> <message> to the <console>. -<Log> <message> to the <console: output>. -<Log> <message> to the <console: error>. -<Log> "literal message" to the <console>. +Log <message> to the <console>. +Log <message> to the <console: output>. +Log <message> to the <console: error>. +Log "literal message" to the <console>. ``` **Qualifiers:** @@ -590,15 +590,15 @@ Outputs messages to console (stdout or stderr). **Examples:** ```aro (* Standard output *) -<Log> "Server started successfully" to the <console>. +Log "Server started successfully" to the <console>. (* Error output *) -<Log> "Warning: Configuration file not found" to the <console: error>. -<Log> <error-message> to the <console: error>. +Log "Warning: Configuration file not found" to the <console: error>. +Log <error-message> to the <console: error>. (* Data pipeline - stdout for data, stderr for diagnostics *) -<Log> <json-data> to the <console>. -<Log> "Processed 1000 records" to the <console: error>. +Log <json-data> to the <console>. +Log "Processed 1000 records" to the <console: error>. ``` **Output Contexts:** @@ -619,15 +619,15 @@ Sends data to external destinations using sink syntax (ARO-0043). **Syntax:** ```aro -<Send> <value> to the <destination>. +Send <value> to the <destination>. ``` **Examples:** ```aro -<Send> "Hello" to the <connection>. -<Send> <data> to the <connection>. -<Send> <email> to the <user: email>. -<Send> <notification> to the <push-service>. +Send "Hello" to the <connection>. +Send <data> to the <connection>. +Send <email> to the <user: email>. +Send <notification> to the <push-service>. ``` **Valid Prepositions:** `to` @@ -640,14 +640,14 @@ Emits domain events. **Syntax:** ```aro -<Emit> [article] <event-type: event> with <data>. +Emit [article] <event-type: event> with <data>. ``` **Examples:** ```aro -<Emit> a <UserCreated: event> with <user>. -<Emit> an <OrderPlaced: event> with <order>. -<Emit> a <PaymentProcessed: event> with <payment>. +Emit a <UserCreated: event> with <user>. +Emit an <OrderPlaced: event> with <order>. +Emit a <PaymentProcessed: event> with <payment>. ``` **Valid Prepositions:** `with` @@ -662,21 +662,21 @@ Sends notifications to users, administrators, or systems. The action automatical **Syntax:** ```aro -<Notify> the <message> to the <recipient>. -<Alert> the <message> to the <recipient>. -<Signal> the <message> to the <recipient>. +Notify the <message> to the <recipient>. +Alert the <message> to the <recipient>. +Signal the <message> to the <recipient>. ``` **Examples:** ```aro (* User notification *) -<Notify> the <welcome-message> to the <user>. +Notify the <welcome-message> to the <user>. (* Admin alert *) -<Alert> the <system-warning> to the <admin>. +Alert the <system-warning> to the <admin>. (* System signal *) -<Signal> the <shutdown-notice> to the <processes>. +Signal the <shutdown-notice> to the <processes>. ``` **NotificationSent Handler:** @@ -684,10 +684,10 @@ Feature sets can subscribe to notification events: ```aro (Log All Notifications: NotificationSent Handler) { - <Extract> the <message> from the <event: message>. - <Extract> the <type> from the <event: type>. - <Log> "Notification [${type}]: ${message}" to the <console>. - <Return> an <OK: status> for the <logging>. + Extract the <message> from the <event: message>. + Extract the <type> from the <event: type>. + Log "Notification [${type}]: ${message}" to the <console>. + Return an <OK: status> for the <logging>. } ``` @@ -707,13 +707,13 @@ Writes to files. **Syntax:** ```aro -<Write> the <data> to the <file: path>. +Write the <data> to the <file: path>. ``` **Examples:** ```aro -<Write> the <content> to the <file: "./output.txt">. -<Write> the <data: JSON> to the <file: "./data.json">. +Write the <content> to the <file: "./output.txt">. +Write the <data: JSON> to the <file: "./data.json">. ``` **Valid Prepositions:** `to` @@ -726,13 +726,13 @@ Appends content to a file. **Syntax:** ```aro -<Append> the <data> to the <file: path>. +Append the <data> to the <file: path>. ``` **Examples:** ```aro -<Append> the <log-line> to the <file: "./logs/app.log">. -<Append> the <entry> to the <file: "./data.txt">. +Append the <log-line> to the <file: "./logs/app.log">. +Append the <entry> to the <file: "./data.txt">. ``` **Valid Prepositions:** `to`, `into` @@ -745,18 +745,18 @@ Lists directory contents. **Syntax:** ```aro -<Create> the <dir-path> with "./path". -<List> the <result> from the <directory: dir-path>. -<List> the <result> from the <directory: dir-path> matching "pattern". -<List> the <result> from the <directory: dir-path> recursively. +Create the <dir-path> with "./path". +List the <result> from the <directory: dir-path>. +List the <result> from the <directory: dir-path> matching "pattern". +List the <result> from the <directory: dir-path> recursively. ``` **Examples:** ```aro -<Create> the <uploads-path> with "./uploads". -<List> the <entries> from the <directory: uploads-path>. -<List> the <aro-files> from the <directory: src-path> matching "*.aro". -<List> the <all-files> from the <directory: project-path> recursively. +Create the <uploads-path> with "./uploads". +List the <entries> from the <directory: uploads-path>. +List the <aro-files> from the <directory: src-path> matching "*.aro". +List the <all-files> from the <directory: project-path> recursively. ``` **Valid Prepositions:** `from` @@ -769,14 +769,14 @@ Gets file or directory metadata. **Syntax:** ```aro -<Stat> the <result> for the <file: path>. -<Stat> the <result> for the <directory: path>. +Stat the <result> for the <file: path>. +Stat the <result> for the <directory: path>. ``` **Examples:** ```aro -<Stat> the <info> for the <file: "./document.pdf">. -<Stat> the <dir-info> for the <directory: "./src">. +Stat the <info> for the <file: "./document.pdf">. +Stat the <dir-info> for the <directory: "./src">. ``` **Result Properties:** @@ -799,14 +799,14 @@ Checks if a file or directory exists. **Syntax:** ```aro -<Exists> the <result> for the <file: path>. -<Exists> the <result> for the <directory: path>. +Exists the <result> for the <file: path>. +Exists the <result> for the <directory: path>. ``` **Examples:** ```aro -<Exists> the <found> for the <file: "./config.json">. -<Exists> the <dir-exists> for the <directory: "./output">. +Exists the <found> for the <file: "./config.json">. +Exists the <dir-exists> for the <directory: "./output">. ``` **Valid Prepositions:** `for` @@ -819,12 +819,12 @@ Creates a directory with all intermediate directories. **Syntax:** ```aro -<Make> the <result> to the <path: path>. +Make the <result> to the <path: path>. ``` **Examples:** ```aro -<Make> the <output-dir> to the <path: "./output/reports/2024">. +Make the <output-dir> to the <path: "./output/reports/2024">. ``` **Valid Prepositions:** `to`, `for` @@ -837,14 +837,14 @@ Copies files or directories. **Syntax:** ```aro -<Copy> the <file: source> to the <destination: dest>. -<Copy> the <directory: source> to the <destination: dest>. +Copy the <file: source> to the <destination: dest>. +Copy the <directory: source> to the <destination: dest>. ``` **Examples:** ```aro -<Copy> the <file: "./template.txt"> to the <destination: "./copy.txt">. -<Copy> the <directory: "./src"> to the <destination: "./backup/src">. +Copy the <file: "./template.txt"> to the <destination: "./copy.txt">. +Copy the <directory: "./src"> to the <destination: "./backup/src">. ``` **Valid Prepositions:** `to` @@ -857,14 +857,14 @@ Moves or renames files and directories. **Syntax:** ```aro -<Move> the <file: source> to the <destination: dest>. -<Move> the <directory: source> to the <destination: dest>. +Move the <file: source> to the <destination: dest>. +Move the <directory: source> to the <destination: dest>. ``` **Examples:** ```aro -<Move> the <file: "./draft.txt"> to the <destination: "./final.txt">. -<Move> the <directory: "./temp"> to the <destination: "./processed">. +Move the <file: "./draft.txt"> to the <destination: "./final.txt">. +Move the <directory: "./temp"> to the <destination: "./processed">. ``` **Valid Prepositions:** `to` @@ -877,15 +877,15 @@ Removes data. **Syntax:** ```aro -<Delete> the <target> from the <source> [where <condition>]. -<Delete> the <file: path>. +Delete the <target> from the <source> [where <condition>]. +Delete the <file: path>. ``` **Examples:** ```aro -<Delete> the <user> from the <user-repository> where id = <user-id>. -<Delete> the <file: "./temp.txt">. -<Delete> the <sessions> from the <repository> where expired = true. +Delete the <user> from the <user-repository> where id = <user-id>. +Delete the <file: "./temp.txt">. +Delete the <sessions> from the <repository> where expired = true. ``` **Valid Prepositions:** `from` @@ -901,21 +901,21 @@ Starts a service. All services use the standardized `with` preposition. **Syntax:** ```aro (* HTTP server from OpenAPI contract *) -<Start> the <http-server> with <contract>. +Start the <http-server> with <contract>. (* Socket server with port configuration *) -<Start> the <socket-server> with { port: 9000 }. +Start the <socket-server> with { port: 9000 }. (* File monitor with directory path *) -<Start> the <file-monitor> with ".". -<Start> the <file-monitor> with { directory: "./data" }. +Start the <file-monitor> with ".". +Start the <file-monitor> with { directory: "./data" }. ``` **Examples:** ```aro -<Start> the <http-server> with <contract>. -<Start> the <socket-server> with { port: 9000 }. -<Start> the <file-monitor> with "./uploads". +Start the <http-server> with <contract>. +Start the <socket-server> with { port: 9000 }. +Start the <file-monitor> with "./uploads". ``` **Valid Prepositions:** `with` @@ -928,14 +928,14 @@ Stops a service gracefully. **Syntax:** ```aro -<Stop> the <service> with <application>. +Stop the <service> with <application>. ``` **Examples:** ```aro -<Stop> the <http-server> with <application>. -<Stop> the <socket-server> with <application>. -<Stop> the <file-monitor> with <application>. +Stop the <http-server> with <application>. +Stop the <socket-server> with <application>. +Stop the <file-monitor> with <application>. ``` **Valid Prepositions:** `with` @@ -948,12 +948,12 @@ Listens for connections. **Syntax:** ```aro -<Listen> on port <number> as <name>. +Listen on port <number> as <name>. ``` **Examples:** ```aro -<Listen> on port 9000 as <socket-server>. +Listen on port 9000 as <socket-server>. ``` **Valid Prepositions:** `on`, `as` @@ -966,13 +966,13 @@ Connects to a service. **Syntax:** ```aro -<Connect> to <host: address> on port <number> as <name>. +Connect to <host: address> on port <number> as <name>. ``` **Examples:** ```aro -<Connect> to <host: "localhost"> on port 5432 as <database>. -<Connect> to <host: "redis.local"> on port 6379 as <cache>. +Connect to <host: "localhost"> on port 5432 as <database>. +Connect to <host: "redis.local"> on port 6379 as <cache>. ``` **Valid Prepositions:** `to`, `on`, `as` @@ -985,14 +985,14 @@ Closes connections. **Syntax:** ```aro -<Close> the <connection>. +Close the <connection>. ``` **Examples:** ```aro -<Close> the <database-connections>. -<Close> the <socket-server>. -<Close> the <connection>. +Close the <database-connections>. +Close the <socket-server>. +Close the <connection>. ``` **Valid Prepositions:** None @@ -1005,13 +1005,13 @@ Makes API calls. **Syntax:** ```aro -<Call> the <result> via <api-reference> [with <data>]. +Call the <result> via <api-reference> [with <data>]. ``` **Examples:** ```aro -<Call> the <result> via <UserAPI: POST /users> with <user-data>. -<Call> the <response> via <PaymentAPI: POST /charge> with <payment>. +Call the <result> via <UserAPI: POST /users> with <user-data>. +Call the <response> via <PaymentAPI: POST /charge> with <payment>. ``` **Valid Prepositions:** `via`, `with` @@ -1024,13 +1024,13 @@ Sends to all connections. **Syntax:** ```aro -<Broadcast> the <message> to the <server>. +Broadcast the <message> to the <server>. ``` **Examples:** ```aro -<Broadcast> the <message> to the <socket-server>. -<Broadcast> the <notification> to the <chat-server> with "User joined". +Broadcast the <message> to the <socket-server>. +Broadcast the <notification> to the <chat-server> with "User joined". ``` **Valid Prepositions:** `to`, `with` @@ -1043,7 +1043,7 @@ Keeps a long-running application alive to process events. **Syntax:** ```aro -<Keepalive> the <application> for the <events>. +Keepalive the <application> for the <events>. ``` **Description:** @@ -1053,15 +1053,15 @@ The `Keepalive` action blocks execution until a shutdown signal is received (SIG ```aro (* HTTP server auto-starts when openapi.yaml is present *) (Application-Start: My API) { - <Log> "API starting..." to the <console>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "API starting..." to the <console>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } (Application-Start: File Watcher) { - <Watch> the <directory> for the <changes> with "./watched". - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Watch the <directory> for the <changes> with "./watched". + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } ``` diff --git a/Book/TheLanguageGuide/AppendixB-Prepositions.md b/Book/TheLanguageGuide/AppendixB-Prepositions.md index 4c86fd2f..4ca0f2de 100644 --- a/Book/TheLanguageGuide/AppendixB-Prepositions.md +++ b/Book/TheLanguageGuide/AppendixB-Prepositions.md @@ -37,22 +37,22 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Extract from request context *) -<Extract> the <user-id> from the <pathParameters: id>. -<Extract> the <body> from the <request: body>. -<Extract> the <token> from the <headers: authorization>. +Extract the <user-id> from the <pathParameters: id>. +Extract the <body> from the <request: body>. +Extract the <token> from the <headers: authorization>. (* Retrieve from repository *) -<Retrieve> the <user> from the <user-repository>. -<Retrieve> the <orders> from the <order-repository> where <status> is "active". +Retrieve the <user> from the <user-repository>. +Retrieve the <orders> from the <order-repository> where <status> is "active". (* Request from external URL *) -<Request> the <data> from "https://api.example.com/users". +Request the <data> from "https://api.example.com/users". (* Read from file *) -<Read> the <config> from the <file> with "config.json". +Read the <config> from the <file> with "config.json". (* Filter from collection *) -<Filter> the <active> from the <users> where <status> is "active". +Filter the <active> from the <users> where <status> is "active". ``` ### Semantic Notes @@ -75,26 +75,26 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Create with data *) -<Create> the <user> with <user-data>. -<Create> the <greeting> with "Hello, World!". -<Create> the <total> with <subtotal> + <tax>. +Create the <user> with <user-data>. +Create the <greeting> with "Hello, World!". +Create the <total> with <subtotal> + <tax>. (* Return with payload *) -<Return> an <OK: status> with <users>. -<Return> a <Created: status> with <user>. +Return an <OK: status> with <users>. +Return a <Created: status> with <user>. (* Emit with event data *) -<Emit> a <UserCreated: event> with <user>. -<Emit> an <OrderPlaced: event> with { orderId: <id>, total: <total> }. +Emit a <UserCreated: event> with <user>. +Emit an <OrderPlaced: event> with { orderId: <id>, total: <total> }. (* Merge with updates *) -<Merge> the <updated> from <existing> with <changes>. +Merge the <updated> from <existing> with <changes>. (* Log to console *) -<Log> "Application started" to the <console>. +Log "Application started" to the <console>. (* Read with path *) -<Read> the <content> from the <file> with "data.json". +Read the <content> from the <file> with "data.json". ``` ### Semantic Notes @@ -117,19 +117,19 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Return for a target *) -<Return> an <OK: status> for the <request>. -<Return> a <NoContent: status> for the <deletion>. +Return an <OK: status> for the <request>. +Return a <NoContent: status> for the <deletion>. (* Log to destination *) -<Log> <message> to the <console>. -<Log> <error> to the <error-log>. +Log <message> to the <console>. +Log <error> to the <error-log>. (* Compute for an input *) -<Compute> the <total> for the <items>. -<Compute> the <hash> for the <password>. +Compute the <total> for the <items>. +Compute the <hash> for the <password>. (* Validate for a type *) -<Validate> the <input> for the <user-type>. +Validate the <input> for the <user-type>. ``` ### Semantic Notes @@ -152,16 +152,16 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Send to destination *) -<Send> the <email> to the <user: email>. -<Send> the <notification> to the <admin>. -<Send> the <request> to "https://api.example.com/webhook". +Send the <email> to the <user: email>. +Send the <notification> to the <admin>. +Send the <request> to "https://api.example.com/webhook". (* Write to file *) -<Write> the <data> to the <file> with "output.json". +Write the <data> to the <file> with "output.json". (* Connect to service *) -<Connect> the <database> to "postgres://localhost/mydb". -<Connect> the <socket> to "localhost:9000". +Connect the <database> to "postgres://localhost/mydb". +Connect the <socket> to "localhost:9000". ``` ### Semantic Notes @@ -184,13 +184,13 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Store into repository *) -<Store> the <user> into the <user-repository>. -<Store> the <order> into the <order-repository>. -<Store> the <cache-entry> into the <cache>. +Store the <user> into the <user-repository>. +Store the <order> into the <order-repository>. +Store the <cache-entry> into the <cache>. (* Transform into format *) -<Transform> the <dto> into the <json>. -<Transform> the <entity> into the <response-model>. +Transform the <dto> into the <json>. +Transform the <entity> into the <response-model>. ``` ### Semantic Notes @@ -213,13 +213,13 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Validate against schema *) -<Validate> the <input> against the <user: schema>. -<Validate> the <password> against the <password-rules>. -<Validate> the <token> against the <auth-service>. +Validate the <input> against the <user: schema>. +Validate the <password> against the <password-rules>. +Validate the <token> against the <auth-service>. (* Compare against reference *) -<Compare> the <old-value> against the <new-value>. -<Compare> the <actual> against the <expected>. +Compare the <old-value> against the <new-value>. +Compare the <actual> against the <expected>. ``` ### Semantic Notes @@ -242,11 +242,11 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Request via proxy *) -<Request> the <data> from "https://api.example.com" via the <proxy>. +Request the <data> from "https://api.example.com" via the <proxy>. (* Send via channel *) -<Send> the <message> to the <user> via the <email-service>. -<Send> the <notification> to the <subscriber> via the <websocket>. +Send the <message> to the <user> via the <email-service>. +Send the <notification> to the <subscriber> via the <websocket>. ``` ### Semantic Notes @@ -269,11 +269,11 @@ ARO uses eight prepositions, each with specific semantic meaning: ```aro (* Start on port *) -<Start> the <http-server> on port 8080. -<Start> the <socket-server> on port 9000. +Start the <http-server> on port 8080. +Start the <socket-server> on port 9000. (* Serve on host *) -<Start> the <http-server> on "0.0.0.0:8080". +Start the <http-server> on "0.0.0.0:8080". ``` ### Semantic Notes @@ -288,14 +288,14 @@ ARO uses eight prepositions, each with specific semantic meaning: | Intent | Preposition | Example | |--------|-------------|---------| -| Pull data in | `from` | `<Extract> the <x> from the <y>` | -| Provide data | `with` | `<Create> the <x> with <y>` | -| Indicate purpose | `for` | `<Return> the <x> for the <y>` | -| Push data out | `to` | `<Send> the <x> to the <y>` | -| Store/transform | `into` | `<Store> the <x> into the <y>` | -| Compare/validate | `against` | `<Validate> the <x> against the <y>` | -| Specify channel | `via` | `<Request> the <x> via the <y>` | -| Specify location | `on` | `<Start> the <x> on <y>` | +| Pull data in | `from` | `Extract the <x> from the <y>` | +| Provide data | `with` | `Create the <x> with <y>` | +| Indicate purpose | `for` | `Return the <x> for the <y>` | +| Push data out | `to` | `Send the <x> to the <y>` | +| Store/transform | `into` | `Store the <x> into the <y>` | +| Compare/validate | `against` | `Validate the <x> against the <y>` | +| Specify channel | `via` | `Request the <x> via the <y>` | +| Specify location | `on` | `Start the <x> on <y>` | --- diff --git a/Book/TheLanguageGuide/AppendixC-Statements.md b/Book/TheLanguageGuide/AppendixC-Statements.md index 6c00d174..be13f6fb 100644 --- a/Book/TheLanguageGuide/AppendixC-Statements.md +++ b/Book/TheLanguageGuide/AppendixC-Statements.md @@ -9,7 +9,7 @@ The fundamental statement type following the Action-Result-Object pattern. ### Syntax ``` -<Action> [article] <result> preposition [article] <object> [modifiers]. +Action [article] <result> preposition [article] <object> [modifiers]. ``` ### Components @@ -26,12 +26,12 @@ The fundamental statement type following the Action-Result-Object pattern. ### Examples ```aro -<Extract> the <user-id> from the <request: parameters>. -<Create> a <user> with <user-data>. -<Return> an <OK: status> for the <request>. -<Store> the <order> into the <order-repository>. -<Retrieve> the <user> from the <repository> where id = <user-id>. -<Start> the <http-server> on port 8080. +Extract the <user-id> from the <request: parameters>. +Create a <user> with <user-data>. +Return an <OK: status> for the <request>. +Store the <order> into the <order-repository>. +Retrieve the <user> from the <repository> where id = <user-id>. +Start the <http-server> on port 8080. ``` ## Publish Statement @@ -41,7 +41,7 @@ Makes a variable globally accessible across feature sets. ### Syntax ``` -<Publish> as <alias> <variable>. +Publish as <alias> <variable>. ``` ### Components @@ -54,8 +54,8 @@ Makes a variable globally accessible across feature sets. ### Example ```aro -<Read> the <config> from the <file: "./config.json">. -<Publish> as <app-config> <config>. +Read the <config> from the <file: "./config.json">. +Publish as <app-config> <config>. ``` ## Guarded Statement (when) @@ -65,7 +65,7 @@ Conditionally executes a statement based on a condition. If the condition is fal ### Syntax ``` -<Action> the <result> preposition the <object> when <condition>. +Action the <result> preposition the <object> when <condition>. ``` ### Conditions @@ -90,39 +90,39 @@ Conditionally executes a statement based on a condition. If the condition is fal ```aro (* Return not found only when user is empty *) -<Return> a <NotFound: status> for the <missing: user> when <user> is empty. +Return a <NotFound: status> for the <missing: user> when <user> is empty. (* Send notification only when user has email *) -<Send> the <notification> to the <user: email> when <user: email> exists. +Send the <notification> to the <user: email> when <user: email> exists. (* Log admin access only for admins *) -<Log> "admin access" to the <audit> when <user: role> = "admin". +Log "admin access" to the <audit> when <user: role> = "admin". (* Early exit on invalid input *) -<Return> a <BadRequest: status> for the <invalid: amount> when <amount> <= 0. +Return a <BadRequest: status> for the <invalid: amount> when <amount> <= 0. (* Combined conditions *) -<Grant> the <access> for the <user> when <user: active> is true and <user: verified> is true. +Grant the <access> for the <user> when <user: active> is true and <user: verified> is true. ``` ### Usage Pattern ```aro (PUT /users/{id}: User API) { - <Extract> the <user-id> from the <request: parameters>. - <Extract> the <updates> from the <request: body>. + Extract the <user-id> from the <request: parameters>. + Extract the <updates> from the <request: body>. (* Early exit guards *) - <Return> a <BadRequest: status> for the <missing: id> when <user-id> is empty. - <Return> a <BadRequest: status> for the <missing: data> when <updates> is empty. + Return a <BadRequest: status> for the <missing: id> when <user-id> is empty. + Return a <BadRequest: status> for the <missing: data> when <updates> is empty. (* Continue with valid input *) - <Retrieve> the <user> from the <repository> where id = <user-id>. - <Return> a <NotFound: status> for the <missing: user> when <user> is empty. + Retrieve the <user> from the <repository> where id = <user-id>. + Return a <NotFound: status> for the <missing: user> when <user> is empty. - <Transform> the <updated-user> from the <user> with <updates>. - <Store> the <updated-user> into the <repository>. - <Return> an <OK: status> with <updated-user>. + Transform the <updated-user> from the <user> with <updates>. + Store the <updated-user> into the <repository>. + Return an <OK: status> with <updated-user>. } ``` @@ -161,18 +161,18 @@ match <variable> { ```aro match <status> { case "pending" { - <Log> "Order is pending" to the <console>. + Log "Order is pending" to the <console>. } case "shipped" { - <Log> "Order has shipped" to the <console>. - <Emit> an <OrderShipped: event> with <order>. + Log "Order has shipped" to the <console>. + Emit an <OrderShipped: event> with <order>. } case "delivered" { - <Log> "Order delivered" to the <console>. - <Emit> an <OrderDelivered: event> with <order>. + Log "Order delivered" to the <console>. + Emit an <OrderDelivered: event> with <order>. } otherwise { - <Log> "Unknown status" to the <console>. + Log "Unknown status" to the <console>. } } ``` @@ -182,18 +182,18 @@ match <status> { ```aro match <user: subscription> { case <premium> where <user: credits> > 0 { - <Grant> the <premium-features> for the <user>. - <Deduct> the <credit> from the <user: account>. + Grant the <premium-features> for the <user>. + Deduct the <credit> from the <user: account>. } case <premium> { - <Notify> the <user> about the <low-credits>. - <Grant> the <basic-features> for the <user>. + Notify the <user> about the <low-credits>. + Grant the <basic-features> for the <user>. } case <basic> { - <Grant> the <basic-features> for the <user>. + Grant the <basic-features> for the <user>. } otherwise { - <Redirect> the <user> to the <subscription-page>. + Redirect the <user> to the <subscription-page>. } } ``` @@ -205,7 +205,7 @@ Exits the feature set with a response. ### Syntax ``` -<Return> [article] <status> [with <data>] [for <context>]. +Return [article] <status> [with <data>] [for <context>]. ``` ### Status Codes @@ -229,12 +229,12 @@ Exits the feature set with a response. ### Examples ```aro -<Return> an <OK: status> with <data>. -<Return> a <Created: status> with <resource>. -<Return> a <NoContent: status> for the <deletion>. -<Return> a <BadRequest: status> with <validation: errors>. -<Return> a <NotFound: status> for the <missing: user>. -<Return> a <Forbidden: status> for the <unauthorized: access>. +Return an <OK: status> with <data>. +Return a <Created: status> with <resource>. +Return a <NoContent: status> for the <deletion>. +Return a <BadRequest: status> with <validation: errors>. +Return a <NotFound: status> for the <missing: user>. +Return a <Forbidden: status> for the <unauthorized: access>. ``` ## Comment @@ -261,14 +261,14 @@ Adds documentation to code. (Process Order: Order Processing) { (* Extract order data from request *) - <Extract> the <order-data> from the <request: body>. + Extract the <order-data> from the <request: body>. (* Validate before processing *) - <Validate> the <order-data> for the <order-schema>. + Validate the <order-data> for the <order-schema>. (* Store and return *) - <Store> the <order> into the <repository>. - <Return> a <Created: status> with <order>. + Store the <order> into the <repository>. + Return a <Created: status> with <order>. } ``` @@ -286,10 +286,10 @@ Filters data in retrieval and deletion. ### Examples ```aro -<Retrieve> the <user> from the <repository> where id = <user-id>. -<Retrieve> the <orders> from the <repository> where status = "pending". -<Retrieve> the <users> from the <repository> where role = "admin" and active = true. -<Delete> the <sessions> from the <repository> where userId = <user-id>. +Retrieve the <user> from the <repository> where id = <user-id>. +Retrieve the <orders> from the <repository> where status = "pending". +Retrieve the <users> from the <repository> where role = "admin" and active = true. +Delete the <sessions> from the <repository> where userId = <user-id>. ``` ## With Clause @@ -307,11 +307,11 @@ Provides additional data or parameters. ### Examples ```aro -<Create> the <user> with <user-data>. -<Create> the <config> with { debug: true, port: 8080 }. -<Transform> the <updated> from the <user> with <updates>. -<Send> the <message> to the <connection> with "Hello, World!". -<Log> "Application started" to the <console>. +Create the <user> with <user-data>. +Create the <config> with { debug: true, port: 8080 }. +Transform the <updated> from the <user> with <updates>. +Send the <message> to the <connection> with "Hello, World!". +Log "Application started" to the <console>. ``` ## On Clause @@ -327,9 +327,9 @@ Specifies ports for network operations. ### Examples ```aro -<Start> the <http-server> on port 8080. -<Listen> on port 9000 as <socket-server>. -<Connect> to <host: "localhost"> on port 5432 as <database>. +Start the <http-server> on port 8080. +Listen on port 9000 as <socket-server>. +Connect to <host: "localhost"> on port 5432 as <database>. ``` ## When Clause @@ -339,15 +339,15 @@ Conditionally executes a statement. ### Syntax ``` -<Action> the <result> preposition the <object> when <condition>. +Action the <result> preposition the <object> when <condition>. ``` ### Examples ```aro -<Return> a <NotFound: status> for the <user> when <user> is empty. -<Log> "Low stock" to the <console> when <stock> < 10. -<Send> the <alert> to the <admin: email> when <errors> > <threshold>. +Return a <NotFound: status> for the <user> when <user> is empty. +Log "Low stock" to the <console> when <stock> < 10. +Send the <alert> to the <admin: email> when <errors> > <threshold>. ``` ## Statement Order @@ -357,22 +357,22 @@ Statements execute sequentially from top to bottom: ```aro (Process Request: Handler) { (* 1. First *) - <Extract> the <data> from the <request: body>. + Extract the <data> from the <request: body>. (* 2. Second *) - <Validate> the <data> for the <schema>. + Validate the <data> for the <schema>. (* 3. Third *) - <Create> the <result> with <data>. + Create the <result> with <data>. (* 4. Fourth *) - <Store> the <result> into the <repository>. + Store the <result> into the <repository>. (* 5. Fifth - ends execution *) - <Return> a <Created: status> with <result>. + Return a <Created: status> with <result>. (* Never executed - after return *) - <Log> "This won't run" to the <console>. + Log "This won't run" to the <console>. } ``` @@ -382,11 +382,11 @@ All statements end with a period (`.`): ```aro (* Correct *) -<Extract> the <data> from the <request>. -<Return> an <OK: status> with <data>. +Extract the <data> from the <request>. +Return an <OK: status> with <data>. (* Incorrect - missing period *) -<Extract> the <data> from the <request> +Extract the <data> from the <request> ``` Match blocks use braces without periods on closing brace: @@ -394,7 +394,7 @@ Match blocks use braces without periods on closing brace: ```aro match <status> { case "active" { - <Return> an <OK: status>. (* Period on inner statement *) + Return an <OK: status>. (* Period on inner statement *) } } (* No period on closing brace *) ``` diff --git a/Book/TheLanguageGuide/Chapter01-WhyARO.md b/Book/TheLanguageGuide/Chapter01-WhyARO.md index a327df05..9d417c31 100644 --- a/Book/TheLanguageGuide/Chapter01-WhyARO.md +++ b/Book/TheLanguageGuide/Chapter01-WhyARO.md @@ -29,7 +29,7 @@ ARO makes specific choices about what it will and won't express: **What ARO Has:** - 50 built-in actions (verbs like Extract, Compute, Return, Emit) -- A fixed sentence structure: `<Action> the <Result> preposition the <Object>` +- A fixed sentence structure: `Action the <Result> preposition the <Object>` - Feature sets that respond to events - First-class support for HTTP, files, and sockets - Native compilation to standalone binaries @@ -79,11 +79,11 @@ Consider this ARO feature set: ```aro (createUser: User API) { - <Extract> the <data> from the <request: body>. - <Validate> the <data> against the <user: schema>. - <Create> the <user> with <data>. - <Emit> a <UserCreated: event> with <user>. - <Return> a <Created: status> with <user>. + Extract the <data> from the <request: body>. + Validate the <data> against the <user: schema>. + Create the <user> with <data>. + Emit a <UserCreated: event> with <user>. + Return a <Created: status> with <user>. } ``` diff --git a/Book/TheLanguageGuide/Chapter02-MentalModel.md b/Book/TheLanguageGuide/Chapter02-MentalModel.md index 4652588f..74f115f6 100644 --- a/Book/TheLanguageGuide/Chapter02-MentalModel.md +++ b/Book/TheLanguageGuide/Chapter02-MentalModel.md @@ -49,7 +49,7 @@ The third component is the **Object**, which represents the input or context for These three components combine to form a complete sentence. Consider this statement: ```aro -<Extract> the <user-id> from the <pathParameters: id>. +Extract the <user-id> from the <pathParameters: id>. ``` The action is Extract, telling us that we are pulling data out of something. The result is user-id, which will hold the extracted value. The object is pathParameters with a qualifier of id, indicating where the data comes from. The preposition "from" establishes that data flows from the path parameters into the user-id variable. @@ -116,9 +116,9 @@ Consider a typical operation: getting a user by their identifier. In an imperati ```aro (getUser: User API) { - <Extract> the <user-id> from the <pathParameters: id>. - <Retrieve> the <user> from the <user-repository> where <id> is <user-id>. - <Return> an <OK: status> with <user>. + Extract the <user-id> from the <pathParameters: id>. + Retrieve the <user> from the <user-repository> where <id> is <user-id>. + Return an <OK: status> with <user>. } ``` diff --git a/Book/TheLanguageGuide/Chapter04-StatementAnatomy.md b/Book/TheLanguageGuide/Chapter04-StatementAnatomy.md index 4bf08381..71ed98eb 100644 --- a/Book/TheLanguageGuide/Chapter04-StatementAnatomy.md +++ b/Book/TheLanguageGuide/Chapter04-StatementAnatomy.md @@ -98,7 +98,7 @@ Array literals are enclosed in square brackets with elements separated by commas Object literals are enclosed in curly braces with fields written as key-colon-value pairs separated by commas. The keys are identifiers; the values can be any valid expression. Object literals allow you to construct structured data inline, which is particularly useful for return values and event payloads. ```aro -<Create> the <user> with { name: "Alice", email: "alice@example.com", active: true }. +Create the <user> with { name: "Alice", email: "alice@example.com", active: true }. ``` ## 4.8 Where Clauses @@ -112,7 +112,7 @@ Conditions in where clauses can use equality checks with "is" or "=" and inequal Where clauses can also appear with Filter actions, where they specify which elements of a collection to include in the result. The semantics are the same: only elements satisfying the condition are included. ```aro -<Retrieve> the <order> from the <order-repository> where id = <order-id>. +Retrieve the <order> from the <order-repository> where id = <order-id>. ``` ## 4.9 When Conditions @@ -126,7 +126,7 @@ When conditions are useful for optional operations—things that should happen o The condition can be any boolean expression. You can reference bound variables, compare values, check for existence, and combine conditions with logical operators. The same expression syntax used elsewhere in ARO applies within when conditions. ```aro -<Send> the <notification> to the <user: email> when <user: notifications> is true. +Send the <notification> to the <user: email> when <user: notifications> is true. ``` ## 4.10 Comments @@ -148,39 +148,39 @@ Having examined each component in isolation, let us see how they combine in comp A minimal statement has an action, an article, a result, a preposition, an article, and an object: ```aro -<Retrieve> the <users> from the <user-repository>. +Retrieve the <users> from the <user-repository>. ``` *Source: [Examples/UserService/users.aro:7](../Examples/UserService/users.aro)* A statement with a qualifier on the result and object adds more specificity: ```aro -<Extract> the <user-id: String> from the <pathParameters: id>. +Extract the <user-id: String> from the <pathParameters: id>. ``` A statement with a literal value provides data inline: ```aro -<Create> the <greeting> with "Hello, World!". +Create the <greeting> with "Hello, World!". ``` A statement with an expression computes a value: ```aro -<Compute> the <total> with <subtotal> + <tax>. +Compute the <total> with <subtotal> + <tax>. ``` A statement with a where clause filters the operation: ```aro -<Retrieve> the <user> from the <user-repository> where <id> is <user-id>. +Retrieve the <user> from the <user-repository> where <id> is <user-id>. ``` *Source: [Examples/UserService/users.aro:14](../Examples/UserService/users.aro)* A statement with a when condition executes conditionally: ```aro -<Send> the <notification> to the <user> when <user: notifications> is true. +Send the <notification> to the <user> when <user: notifications> is true. ``` Each of these statements follows the same fundamental pattern while using optional elements to add precision and expressiveness. The pattern is the constant; the optional elements are the variables. Once you internalize the pattern, you can read and write any ARO statement fluently. diff --git a/Book/TheLanguageGuide/Chapter06-DataFlow.md b/Book/TheLanguageGuide/Chapter06-DataFlow.md index 354cfece..5bb8cc4d 100644 --- a/Book/TheLanguageGuide/Chapter06-DataFlow.md +++ b/Book/TheLanguageGuide/Chapter06-DataFlow.md @@ -59,7 +59,7 @@ The compiler enforces immutability at compile-time. If you attempt to bind a var ``` error: Cannot rebind variable 'value' - variables are immutable Hint: Create a new variable with a different name instead - Example: <Create> the <value-updated> with "second" + Example: Create the <value-updated> with "second" ``` This compile-time check prevents a common class of bugs where variables change unexpectedly and makes it easier to reason about program behavior. The runtime also includes a safety check as a defense against compiler bugs, but in normal operation, all rebinding attempts are caught during compilation. @@ -71,20 +71,20 @@ To work with transformed values, create new variables with descriptive names tha ```aro (* Immutability Example *) (Process Data: Computation) { - <Create> the <value> with 10. + Create the <value> with 10. (* ❌ This would fail: Cannot rebind 'value' *) - (* <Compute> the <value> from <value> + 5. *) + (* Compute the <value> from <value> + 5. *) (* ✅ Correct: Create new variable *) - <Compute> the <value-incremented> from <value> + 5. - <Compute> the <value-doubled> from <value-incremented> * 2. + Compute the <value-incremented> from <value> + 5. + Compute the <value-doubled> from <value-incremented> * 2. - <Log> <value> to the <console>. (* 10 *) - <Log> <value-incremented> to the <console>. (* 15 *) - <Log> <value-doubled> to the <console>. (* 30 *) + Log <value> to the <console>. (* 10 *) + Log <value-incremented> to the <console>. (* 15 *) + Log <value-doubled> to the <console>. (* 30 *) - <Return> an <OK: status> with <value-doubled>. + Return an <OK: status> with <value-doubled>. } ``` @@ -97,11 +97,11 @@ Loop variables are immutable within each iteration. Each iteration gets fresh bi ```aro for each <item> in <items> { (* ❌ Cannot rebind loop variable *) - (* <Compute> the <item> from <item> + 1. *) + (* Compute the <item> from <item> + 1. *) (* ✅ Create new variable from loop variable *) - <Compute> the <item-incremented> from <item> + 1. - <Log> <item-incremented> to the <console>. + Compute the <item-incremented> from <item> + 1. + Log <item-incremented> to the <console>. } ``` @@ -159,7 +159,7 @@ Events provide a structured way to pass data between feature sets while maintain Repositories act as shared persistent storage. One feature set can store a value to a repository, and another feature set can retrieve it later. This communication is asynchronous in the sense that the retriever does not need to execute while the storer is executing. The repository holds the data between executions. This is appropriate for persistent data that outlives individual requests. -Repository names must end with `-repository`—this is not merely a convention but a requirement that enables the runtime to identify storage targets. When you write `<Store> the <user> into the <user-repository>`, the runtime recognizes `user-repository` as persistent storage because of its suffix. Names like `users` or `user-data` would not trigger repository semantics. +Repository names must end with `-repository`—this is not merely a convention but a requirement that enables the runtime to identify storage targets. When you write `Store the <user> into the <user-repository>`, the runtime recognizes `user-repository` as persistent storage because of its suffix. Names like `users` or `user-data` would not trigger repository semantics. Repositories are scoped to business activities by default. A `user-repository` accessed by feature sets with the business activity "User Management" is separate from a `user-repository` accessed by feature sets with the business activity "Admin Tools". This scoping prevents unintended data sharing between different domains of your application. diff --git a/Book/TheLanguageGuide/Chapter07-ExportActions.md b/Book/TheLanguageGuide/Chapter07-ExportActions.md index 0fec11d0..c57013c8 100644 --- a/Book/TheLanguageGuide/Chapter07-ExportActions.md +++ b/Book/TheLanguageGuide/Chapter07-ExportActions.md @@ -67,13 +67,13 @@ The simplest form of Store appends a value to a repository: ```aro (createUser: User API) { - <Extract> the <user-data> from the <request: body>. - <Create> the <user> with <user-data>. + Extract the <user-data> from the <request: body>. + Create the <user> with <user-data>. (* Store saves the user to the repository *) - <Store> the <user> into the <user-repository>. + Store the <user> into the <user-repository>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } ``` @@ -86,23 +86,23 @@ Data stored in a repository can be retrieved by any feature set: ```aro (listUsers: User API) { (* Retrieve all users from the repository *) - <Retrieve> the <users> from the <user-repository>. - <Return> an <OK: status> with <users>. + Retrieve the <users> from the <user-repository>. + Return an <OK: status> with <users>. } (getUser: User API) { - <Extract> the <id> from the <pathParameters: id>. + Extract the <id> from the <pathParameters: id>. (* Retrieve with a filter *) - <Retrieve> the <user> from the <user-repository> where id = <id>. - <Return> an <OK: status> with <user>. + Retrieve the <user> from the <user-repository> where id = <id>. + Return an <OK: status> with <user>. } ``` The where clause filters the repository contents. Multiple conditions can be combined: ```aro -<Retrieve> the <orders> from the <order-repository> +Retrieve the <orders> from the <order-repository> where status = "pending" and customer = <customer-id>. ``` @@ -113,13 +113,13 @@ When data is stored, updated, or deleted in a repository, observers can react au ```aro (* This observer runs automatically when user-repository changes *) (Audit Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Extract> the <entityId> from the <event: entityId>. + Extract the <changeType> from the <event: changeType>. + Extract the <entityId> from the <event: entityId>. - <Compute> the <message> from "[AUDIT] user-repository: " + <changeType> + " (id: " + <entityId> + ")". - <Log> <message> to the <console>. + Compute the <message> from "[AUDIT] user-repository: " + <changeType> + " (id: " + <entityId> + ")". + Log <message> to the <console>. - <Return> an <OK: status> for the <audit>. + Return an <OK: status> for the <audit>. } ``` @@ -154,14 +154,14 @@ Emit creates a domain event with a type and payload: ```aro (createUser: User API) { - <Extract> the <user-data> from the <request: body>. - <Create> the <user> with <user-data>. - <Store> the <user> into the <user-repository>. + Extract the <user-data> from the <request: body>. + Create the <user> with <user-data>. + Store the <user> into the <user-repository>. (* Emit notifies interested handlers *) - <Emit> a <UserCreated: event> with <user>. + Emit a <UserCreated: event> with <user>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } ``` @@ -172,30 +172,30 @@ The event type is derived from the result descriptor. In this case, `UserCreated Handlers receive the event payload and can extract data from it: ```aro -(* Triggered by <Emit> a <UserCreated: event> with <user> *) +(* Triggered by Emit a <UserCreated: event> with <user> *) (Send Welcome Email: UserCreated Handler) { - <Extract> the <user> from the <event: user>. - <Extract> the <email> from the <user: email>. + Extract the <user> from the <event: user>. + Extract the <email> from the <user: email>. - <Send> the <welcome-email> to the <email-service> with { + Send the <welcome-email> to the <email-service> with { to: <email>, subject: "Welcome!", template: "welcome" }. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } (* Another handler for the same event *) (Track Signup: UserCreated Handler) { - <Extract> the <user> from the <event: user>. + Extract the <user> from the <event: user>. - <Send> the <analytics-event> to the <analytics-service> with { + Send the <analytics-event> to the <analytics-service> with { event: "user_signup", properties: <user> }. - <Return> an <OK: status> for the <tracking>. + Return an <OK: status> for the <tracking>. } ``` @@ -208,24 +208,24 @@ Handlers can emit additional events, creating processing chains: ```aro (* OrderPlaced triggers inventory reservation *) (Reserve Inventory: OrderPlaced Handler) { - <Extract> the <order> from the <event: order>. - <Update> the <inventory> for the <order: items>. + Extract the <order> from the <event: order>. + Update the <inventory> for the <order: items>. (* Continue the chain *) - <Emit> an <InventoryReserved: event> with <order>. + Emit an <InventoryReserved: event> with <order>. - <Return> an <OK: status> for the <reservation>. + Return an <OK: status> for the <reservation>. } (* InventoryReserved triggers payment *) (Process Payment: InventoryReserved Handler) { - <Extract> the <order> from the <event: order>. - <Send> the <charge> to the <payment-gateway> with <order>. + Extract the <order> from the <event: order>. + Send the <charge> to the <payment-gateway> with <order>. (* Continue the chain *) - <Emit> a <PaymentProcessed: event> with <order>. + Emit a <PaymentProcessed: event> with <order>. - <Return> an <OK: status> for the <payment>. + Return an <OK: status> for the <payment>. } ``` @@ -253,13 +253,13 @@ Publish registers a value under an alias: ```aro (Application-Start: Config Loader) { - <Read> the <config-data> from the <file: "./config.json">. - <Parse> the <config: JSON> from the <config-data>. + Read the <config-data> from the <file: "./config.json">. + Parse the <config: JSON> from the <config-data>. (* Make config available to all feature sets *) - <Publish> as <app-config> <config>. + Publish as <app-config> <config>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -272,9 +272,9 @@ Published values can be referenced directly by their alias: ```aro (getApiUrl: Configuration Handler) { (* app-config was published at startup *) - <Extract> the <url> from the <app-config: apiUrl>. + Extract the <url> from the <app-config: apiUrl>. - <Return> an <OK: status> with <url>. + Return an <OK: status> with <url>. } ``` @@ -351,13 +351,13 @@ A common mistake is emitting an event when you need persistent data: ```aro (* WRONG: Events are transient *) (createMessage: Chat API) { - <Extract> the <message-data> from the <request: body>. - <Create> the <message> with <message-data>. + Extract the <message-data> from the <request: body>. + Create the <message> with <message-data>. (* This event disappears after handlers complete! *) - <Emit> a <MessageCreated: event> with <message>. + Emit a <MessageCreated: event> with <message>. - <Return> a <Created: status> with <message>. + Return a <Created: status> with <message>. } (listMessages: Chat API) { @@ -371,22 +371,22 @@ The fix is to Store the data: ```aro (* CORRECT: Store for persistence, Emit for notifications *) (createMessage: Chat API) { - <Extract> the <message-data> from the <request: body>. - <Create> the <message> with <message-data>. + Extract the <message-data> from the <request: body>. + Create the <message> with <message-data>. (* Store the message for later retrieval *) - <Store> the <message> into the <message-repository>. + Store the <message> into the <message-repository>. (* Also emit for any handlers that want to react *) - <Emit> a <MessageCreated: event> with <message>. + Emit a <MessageCreated: event> with <message>. - <Return> a <Created: status> with <message>. + Return a <Created: status> with <message>. } (listMessages: Chat API) { (* Now we can retrieve stored messages *) - <Retrieve> the <messages> from the <message-repository>. - <Return> an <OK: status> with <messages>. + Retrieve the <messages> from the <message-repository>. + Return an <OK: status> with <messages>. } ``` @@ -397,18 +397,18 @@ Another mistake is storing data just to trigger an observer when Emit would be c ```aro (* AWKWARD: Using store just to trigger behavior *) (processPayment: Payment API) { - <Extract> the <payment> from the <request: body>. + Extract the <payment> from the <request: body>. (* Storing just to trigger the observer *) - <Store> the <payment> into the <payment-notification-repository>. + Store the <payment> into the <payment-notification-repository>. - <Return> an <OK: status> with <payment>. + Return an <OK: status> with <payment>. } (Send Receipt: payment-notification-repository Observer) { (* This works but is awkward *) - <Extract> the <payment> from the <event: newValue>. - <Send> the <receipt> to the <email-service>. + Extract the <payment> from the <event: newValue>. + Send the <receipt> to the <email-service>. } ``` @@ -417,17 +417,17 @@ The fix is to use Emit for reactive behavior: ```aro (* BETTER: Use Emit for reactive communication *) (processPayment: Payment API) { - <Extract> the <payment> from the <request: body>. + Extract the <payment> from the <request: body>. (* Emit for handlers that need to react *) - <Emit> a <PaymentProcessed: event> with <payment>. + Emit a <PaymentProcessed: event> with <payment>. - <Return> an <OK: status> with <payment>. + Return an <OK: status> with <payment>. } (Send Receipt: PaymentProcessed Handler) { - <Extract> the <payment> from the <event: payment>. - <Send> the <receipt> to the <email-service>. + Extract the <payment> from the <event: payment>. + Send the <receipt> to the <email-service>. } ``` @@ -440,13 +440,13 @@ Publish is sometimes overused when Emit would provide better decoupling: ```aro (* QUESTIONABLE: Publishing user for other feature sets *) (createUser: User API) { - <Create> the <user> with <user-data>. - <Store> the <user> into the <user-repository>. + Create the <user> with <user-data>. + Store the <user> into the <user-repository>. (* Publishing forces other feature sets to poll for this value *) - <Publish> as <latest-user> <user>. + Publish as <latest-user> <user>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } ``` @@ -455,13 +455,13 @@ The problem is that other feature sets must know to check for the published valu ```aro (* BETTER: Emit notifies interested parties automatically *) (createUser: User API) { - <Create> the <user> with <user-data>. - <Store> the <user> into the <user-repository>. + Create the <user> with <user-data>. + Store the <user> into the <user-repository>. (* Handlers are triggered automatically *) - <Emit> a <UserCreated: event> with <user>. + Emit a <UserCreated: event> with <user>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } ``` @@ -477,15 +477,15 @@ Here is a realistic example that uses all three export actions appropriately. Th ```aro (Application-Start: User Service) { - <Read> the <config-data> from the <file: "./config.json">. - <Parse> the <config: JSON> from the <config-data>. + Read the <config-data> from the <file: "./config.json">. + Parse the <config: JSON> from the <config-data>. (* Publish config for all feature sets *) - <Publish> as <app-config> <config>. + Publish as <app-config> <config>. - <Start> the <http-server> with <contract>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Start the <http-server> with <contract>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } ``` @@ -493,32 +493,32 @@ Here is a realistic example that uses all three export actions appropriately. Th ```aro (createUser: User API) { - <Extract> the <user-data> from the <request: body>. - <Create> the <user> with <user-data>. + Extract the <user-data> from the <request: body>. + Create the <user> with <user-data>. (* Store for persistence — we need to retrieve users later *) - <Store> the <user> into the <user-repository>. + Store the <user> into the <user-repository>. (* Emit for reactive behavior — handlers will send emails, track analytics *) - <Emit> a <UserCreated: event> with <user>. + Emit a <UserCreated: event> with <user>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } (getUser: User API) { - <Extract> the <id> from the <pathParameters: id>. + Extract the <id> from the <pathParameters: id>. (* Retrieve stored user *) - <Retrieve> the <user> from the <user-repository> where id = <id>. + Retrieve the <user> from the <user-repository> where id = <id>. - <Return> an <OK: status> with <user>. + Return an <OK: status> with <user>. } (listUsers: User API) { (* Retrieve all stored users *) - <Retrieve> the <users> from the <user-repository>. + Retrieve the <users> from the <user-repository>. - <Return> an <OK: status> with <users>. + Return an <OK: status> with <users>. } ``` @@ -527,30 +527,30 @@ Here is a realistic example that uses all three export actions appropriately. Th ```aro (* Send welcome email when user is created *) (Send Welcome Email: UserCreated Handler) { - <Extract> the <user> from the <event: user>. - <Extract> the <email> from the <user: email>. + Extract the <user> from the <event: user>. + Extract the <email> from the <user: email>. (* Access published config *) - <Extract> the <from-address> from the <app-config: email.fromAddress>. + Extract the <from-address> from the <app-config: email.fromAddress>. - <Send> the <welcome-email> to the <email-service> with { + Send the <welcome-email> to the <email-service> with { to: <email>, from: <from-address>, subject: "Welcome to our service!", template: "welcome" }. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } (* Track signup in analytics *) (Track Signup: UserCreated Handler) { - <Extract> the <user> from the <event: user>. + Extract the <user> from the <event: user>. (* Access published config *) - <Extract> the <analytics-key> from the <app-config: analytics.apiKey>. + Extract the <analytics-key> from the <app-config: analytics.apiKey>. - <Send> the <analytics-event> to the <analytics-service> with { + Send the <analytics-event> to the <analytics-service> with { apiKey: <analytics-key>, event: "user_signup", properties: { @@ -560,7 +560,7 @@ Here is a realistic example that uses all three export actions appropriately. Th } }. - <Return> an <OK: status> for the <tracking>. + Return an <OK: status> for the <tracking>. } ``` @@ -569,14 +569,14 @@ Here is a realistic example that uses all three export actions appropriately. Th ```aro (* Audit all changes to user repository *) (Audit User Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Extract> the <entityId> from the <event: entityId>. - <Extract> the <timestamp> from the <event: timestamp>. + Extract the <changeType> from the <event: changeType>. + Extract the <entityId> from the <event: entityId>. + Extract the <timestamp> from the <event: timestamp>. - <Compute> the <message> from "[AUDIT] " + <timestamp> + " user-repository: " + <changeType> + " (id: " + <entityId> + ")". - <Log> <message> to the <console>. + Compute the <message> from "[AUDIT] " + <timestamp> + " user-repository: " + <changeType> + " (id: " + <entityId> + ")". + Log <message> to the <console>. - <Return> an <OK: status> for the <audit>. + Return an <OK: status> for the <audit>. } ``` diff --git a/Book/TheLanguageGuide/Chapter08-Computations.md b/Book/TheLanguageGuide/Chapter08-Computations.md index 62b28bbb..8924e758 100644 --- a/Book/TheLanguageGuide/Chapter08-Computations.md +++ b/Book/TheLanguageGuide/Chapter08-Computations.md @@ -65,7 +65,7 @@ The **length** and **count** operations count elements—characters in strings, The **identity** operation, while seemingly trivial, serves an important purpose: it allows arithmetic expressions to be written naturally: ```aro -<Compute> the <total> from <price> * <quantity>. +Compute the <total> from <price> * <quantity>. ``` Here, the expression `<price> * <quantity>` is the actual computation. The result binds to `total`. This is identity in action—the expression's result passes through unchanged. @@ -89,9 +89,9 @@ The standard arithmetic operators work on numeric values: | `%` | Modulo (remainder) | `<index> % 2` | ```aro -<Compute> the <subtotal> from <price> * <quantity>. -<Compute> the <total> from <subtotal> + <tax>. -<Compute> the <average> from <sum> / <count>. +Compute the <subtotal> from <price> * <quantity>. +Compute the <total> from <subtotal> + <tax>. +Compute the <average> from <sum> / <count>. ``` ### String Concatenation @@ -99,9 +99,9 @@ The standard arithmetic operators work on numeric values: ARO uses `++` for string concatenation, distinct from the `+` arithmetic operator: ```aro -<Compute> the <greeting> from "Hello, " ++ <name> ++ "!". -<Compute> the <full-name> from <first-name> ++ " " ++ <last-name>. -<Compute> the <path> from <directory> ++ "/" ++ <filename>. +Compute the <greeting> from "Hello, " ++ <name> ++ "!". +Compute the <full-name> from <first-name> ++ " " ++ <last-name>. +Compute the <path> from <directory> ++ "/" ++ <filename>. ``` Why `++` instead of `+`? This design choice provides **type clarity**: @@ -154,8 +154,8 @@ When expressions contain multiple operators, ARO evaluates them in this order (h Use parentheses to override precedence: ```aro -<Compute> the <with-tax> from <price> * (1 + <tax-rate>). -<Compute> the <result> from (<a> + <b>) * <c>. +Compute the <with-tax> from <price> * (1 + <tax-rate>). +Compute the <result> from (<a> + <b>) * <c>. ``` ### Type Behavior @@ -174,17 +174,17 @@ When types don't match, ARO reports a clear error rather than guessing your inte ```aro (* Error: Cannot add String and Integer *) -<Compute> the <result> from "5" + 3. +Compute the <result> from "5" + 3. (* Correct: Use ++ for string building *) -<Compute> the <result> from "Count: " ++ <count>. +Compute the <result> from "Count: " ++ <count>. ``` For explicit type conversion, use the Transform action: ```aro -<Transform> the <count-string> from <count> as String. -<Transform> the <amount-int> from <amount> as Integer. +Transform the <count-string> from <count> as String. +Transform the <amount-int> from <amount> as Integer. ``` ### Short-Circuit Evaluation @@ -214,7 +214,7 @@ Within the same precedence level, operators evaluate **left-to-right**: ```aro (* Left-to-right: (10 - 5) - 2 = 3, not 10 - (5 - 2) = 7 *) -<Compute> the <result> from 10 - 5 - 2. +Compute the <result> from 10 - 5 - 2. ``` Method-style accessors (`.` and `[]`) bind tightest and chain naturally: @@ -234,8 +234,8 @@ Method-style accessors (`.` and `[]`) bind tightest and chain naturally: A subtle problem arises when you need multiple results of the same operation. Consider computing the lengths of two different messages: ```aro -<Compute> the <length> from the <greeting>. -<Compute> the <length> from the <farewell>. (* Compile error! *) +Compute the <length> from the <greeting>. +Compute the <length> from the <farewell>. (* Compile error! *) ``` Since ARO variables are immutable, the compiler rejects the second statement—you cannot rebind a name that already exists. This is a compile-time error, not a silent overwrite. @@ -243,14 +243,14 @@ Since ARO variables are immutable, the compiler rejects the second statement—y The solution is the **qualifier-as-name** syntax. In this pattern, the qualifier specifies the operation while the base becomes the variable name: ```aro -<Compute> the <greeting-length: length> from the <greeting>. -<Compute> the <farewell-length: length> from the <farewell>. +Compute the <greeting-length: length> from the <greeting>. +Compute the <farewell-length: length> from the <farewell>. ``` Now both lengths exist with distinct names. You can compare them: ```aro -<Compare> the <greeting-length> against the <farewell-length>. +Compare the <greeting-length> against the <farewell-length>. ``` This syntax separates two concerns that were previously conflated: @@ -260,12 +260,12 @@ This syntax separates two concerns that were previously conflated: The same pattern works with all computed operations: ```aro -<Compute> the <name-upper: uppercase> from the <name>. -<Compute> the <name-lower: lowercase> from the <name>. -<Compute> the <password-hash: hash> from the <password>. +Compute the <name-upper: uppercase> from the <name>. +Compute the <name-lower: lowercase> from the <name>. +Compute the <password-hash: hash> from the <password>. ``` -For backward compatibility, the original syntax still works. Writing `<Compute> the <length> from <msg>.` recognizes `length` as both the variable name and the operation. +For backward compatibility, the original syntax still works. Writing `Compute the <length> from <msg>.` recognizes `length` as both the variable name and the operation. --- @@ -308,29 +308,29 @@ When working with collections, you often need to find commonalities or differenc The most common use case is comparing two lists: ```aro -<Create> the <list-a> with [2, 3, 5]. -<Create> the <list-b> with [1, 2, 3, 4]. +Create the <list-a> with [2, 3, 5]. +Create the <list-b> with [1, 2, 3, 4]. -<Compute> the <common: intersect> from <list-a> with <list-b>. +Compute the <common: intersect> from <list-a> with <list-b>. (* Result: [2, 3] — elements in both *) -<Compute> the <only-in-a: difference> from <list-a> with <list-b>. +Compute the <only-in-a: difference> from <list-a> with <list-b>. (* Result: [5] — elements in A but not B *) -<Compute> the <all: union> from <list-a> with <list-b>. +Compute the <all: union> from <list-a> with <list-b>. (* Result: [2, 3, 5, 1, 4] — all unique elements *) ``` Set operations use **multiset semantics** for duplicates. When lists contain repeated elements, the intersection preserves duplicates up to the minimum count in either list: ```aro -<Create> the <a> with [1, 2, 2, 3]. -<Create> the <b> with [2, 2, 2, 4]. +Create the <a> with [1, 2, 2, 3]. +Create the <b> with [2, 2, 2, 4]. -<Compute> the <common: intersect> from <a> with <b>. +Compute the <common: intersect> from <a> with <b>. (* Result: [2, 2] — two 2s appear in both *) -<Compute> the <remaining: difference> from <a> with <b>. +Compute the <remaining: difference> from <a> with <b>. (* Result: [1, 3] — removes two 2s from a *) ``` @@ -339,13 +339,13 @@ Set operations use **multiset semantics** for duplicates. When lists contain rep The same operations work on strings at the character level: ```aro -<Compute> the <shared: intersect> from "hello" with "bello". +Compute the <shared: intersect> from "hello" with "bello". (* Result: "ello" — characters in both, preserving order *) -<Compute> the <unique: difference> from "hello" with "bello". +Compute the <unique: difference> from "hello" with "bello". (* Result: "h" — characters in first, not in second *) -<Compute> the <combined: union> from "hello" with "bello". +Compute the <combined: union> from "hello" with "bello". (* Result: "hellob" — all unique characters *) ``` @@ -354,27 +354,27 @@ The same operations work on strings at the character level: For objects, set operations perform **deep recursive comparison**. The intersection finds keys where both objects have matching values: ```aro -<Create> the <obj-a> with { +Create the <obj-a> with { name: "Alice", age: 30, address: { city: "NYC", zip: "10001" } }. -<Create> the <obj-b> with { +Create the <obj-b> with { name: "Alice", age: 31, address: { city: "NYC", state: "NY" } }. -<Compute> the <common: intersect> from <obj-a> with <obj-b>. +Compute the <common: intersect> from <obj-a> with <obj-b>. (* Result: { name: "Alice", address: { city: "NYC" } } *) (* Only fields with matching values are included *) -<Compute> the <diff: difference> from <obj-a> with <obj-b>. +Compute the <diff: difference> from <obj-a> with <obj-b>. (* Result: { age: 30, address: { zip: "10001" } } *) (* Fields in A that differ from or don't exist in B *) -<Compute> the <merged: union> from <obj-a> with <obj-b>. +Compute the <merged: union> from <obj-a> with <obj-b>. (* Result: merged object with A winning conflicts *) ``` @@ -405,15 +405,15 @@ When the Compute action executes, it first checks for a registered computation s A cryptography plugin might provide: ```aro -<Compute> the <password-hash: sha256> from the <password>. -<Compute> the <signature: hmac> from the <message>. +Compute the <password-hash: sha256> from the <password>. +Compute the <signature: hmac> from the <message>. ``` A formatting plugin might provide: ```aro -<Compute> the <formatted-date: iso8601> from the <timestamp>. -<Compute> the <money-display: currency> from the <amount>. +Compute the <formatted-date: iso8601> from the <timestamp>. +Compute the <money-display: currency> from the <amount>. ``` The syntax remains consistent regardless of whether the operation is built-in or plugin-provided. This uniformity means you can start with built-in operations and add plugins later without changing how your code reads. @@ -429,33 +429,33 @@ Several patterns emerge in how computations are used within feature sets. **Derived values** compute new data from existing bindings: ```aro -<Extract> the <price> from the <product: price>. -<Extract> the <quantity> from the <order: quantity>. -<Compute> the <subtotal> from <price> * <quantity>. -<Compute> the <tax> from <subtotal> * 0.08. -<Compute> the <total> from <subtotal> + <tax>. +Extract the <price> from the <product: price>. +Extract the <quantity> from the <order: quantity>. +Compute the <subtotal> from <price> * <quantity>. +Compute the <tax> from <subtotal> * 0.08. +Compute the <total> from <subtotal> + <tax>. ``` **Normalization** ensures consistent data formats: ```aro -<Extract> the <email> from the <input: email>. -<Compute> the <normalized-email: lowercase> from the <email>. +Extract the <email> from the <input: email>. +Compute the <normalized-email: lowercase> from the <email>. ``` **Chained transformations** build complex results step by step: ```aro -<Compute> the <base> from <quantity> * <unit-price>. -<Compute> the <discounted> from <base> * (1 - <discount-rate>). -<Compute> the <with-tax> from <discounted> * (1 + <tax-rate>). +Compute the <base> from <quantity> * <unit-price>. +Compute the <discounted> from <base> * (1 - <discount-rate>). +Compute the <with-tax> from <discounted> * (1 + <tax-rate>). ``` **Aggregation** combines collection data: ```aro -<Retrieve> the <orders> from the <order-repository>. -<Compute> the <order-count: count> from the <orders>. +Retrieve the <orders> from the <order-repository>. +Compute the <order-count: count> from the <orders>. ``` Each pattern follows the read-transform-bind rhythm. Data flows forward, transformations produce new values, and the symbol table accumulates bindings that subsequent statements can use. diff --git a/Book/TheLanguageGuide/Chapter09-QualifierSyntax.md b/Book/TheLanguageGuide/Chapter09-QualifierSyntax.md index 0a03961f..f28ad676 100644 --- a/Book/TheLanguageGuide/Chapter09-QualifierSyntax.md +++ b/Book/TheLanguageGuide/Chapter09-QualifierSyntax.md @@ -28,8 +28,8 @@ When using actions like Compute, Validate, Transform, or Sort, the qualifier spe Consider computing lengths of multiple strings: ```aro -<Compute> the <length> from the <greeting>. -<Compute> the <length> from the <farewell>. +Compute the <length> from the <greeting>. +Compute the <length> from the <farewell>. ``` Both statements attempt to bind to `length`. Since ARO variables are immutable within a scope, the second overwrites the first. You lose the greeting's length. @@ -39,14 +39,14 @@ Both statements attempt to bind to `length`. Since ARO variables are immutable w Separate the variable name from the operation: ```aro -<Compute> the <greeting-length: length> from the <greeting>. -<Compute> the <farewell-length: length> from the <farewell>. +Compute the <greeting-length: length> from the <greeting>. +Compute the <farewell-length: length> from the <farewell>. ``` Now `greeting-length` holds 12 and `farewell-length` holds 8. Both values exist simultaneously, ready for comparison: ```aro -<Compare> the <greeting-length> against the <farewell-length>. +Compare the <greeting-length> against the <farewell-length>. ``` ### Available Operations by Action @@ -62,17 +62,17 @@ Now `greeting-length` holds 12 and `farewell-length` holds 8. Both values exist ```aro (* Multiple computations with distinct names *) -<Compute> the <name-upper: uppercase> from the <name>. -<Compute> the <name-lower: lowercase> from the <name>. -<Compute> the <name-len: length> from the <name>. +Compute the <name-upper: uppercase> from the <name>. +Compute the <name-lower: lowercase> from the <name>. +Compute the <name-len: length> from the <name>. (* Validation with named results *) -<Validate> the <email-valid: email> for the <input-email>. -<Validate> the <age-valid: numeric> for the <input-age>. +Validate the <email-valid: email> for the <input-email>. +Validate the <age-valid: numeric> for the <input-age>. (* Transformations *) -<Transform> the <user-json: json> from the <user>. -<Transform> the <count-str: string> from the <count>. +Transform the <user-json: json> from the <user>. +Transform the <count-str: string> from the <count>. ``` --- @@ -85,13 +85,13 @@ When accessing data from objects, events, or requests, the qualifier navigates t ```aro (* Extract user from event payload *) -<Extract> the <user> from the <event: user>. +Extract the <user> from the <event: user>. (* Extract body from request *) -<Extract> the <data> from the <request: body>. +Extract the <data> from the <request: body>. (* Extract id from path parameters *) -<Extract> the <user-id> from the <pathParameters: id>. +Extract the <user-id> from the <pathParameters: id>. ``` ### Deep Navigation @@ -100,27 +100,27 @@ For nested structures, use dot-separated paths: ```aro (* Access deeply nested data *) -<Extract> the <city> from the <user: address.city>. -<Extract> the <zip> from the <user: address.postal-code>. +Extract the <city> from the <user: address.city>. +Extract the <zip> from the <user: address.postal-code>. (* Navigate through arrays and objects *) -<Extract> the <first-name> from the <response: data.users.0.name>. +Extract the <first-name> from the <response: data.users.0.name>. ``` ### Common Patterns ```aro (* HTTP request handling *) -<Extract> the <auth-token> from the <request: headers.Authorization>. -<Extract> the <content-type> from the <request: headers.Content-Type>. +Extract the <auth-token> from the <request: headers.Authorization>. +Extract the <content-type> from the <request: headers.Content-Type>. (* Event handling *) -<Extract> the <order> from the <event: payload.order>. -<Extract> the <customer-id> from the <event: payload.order.customer-id>. +Extract the <order> from the <event: payload.order>. +Extract the <customer-id> from the <event: payload.order.customer-id>. (* Configuration access *) -<Extract> the <timeout> from the <config: server.timeout>. -<Extract> the <max-retries> from the <config: server.retry.max-attempts>. +Extract the <timeout> from the <config: server.timeout>. +Extract the <max-retries> from the <config: server.retry.max-attempts>. ``` --- @@ -131,13 +131,13 @@ For data pipeline operations (Filter, Reduce, Map), you can optionally specify r ```aro (* Without type - inferred automatically *) -<Filter> the <active-users> from the <users> where <active> is true. +Filter the <active-users> from the <users> where <active> is true. (* With explicit type using 'as' *) -<Filter> the <active-users> as List<User> from the <users> where <active> is true. +Filter the <active-users> as List<User> from the <users> where <active> is true. (* Reduce with type for precision *) -<Reduce> the <total> as Float from the <orders> with sum(<amount>). +Reduce the <total> as Float from the <orders> with sum(<amount>). ``` Type annotations are **optional** because ARO infers result types from the operation. Use explicit types when: @@ -155,13 +155,13 @@ See ARO-0038 for the full specification. A natural question arises: what happens when data contains a field named like an operation? ```aro -<Create> the <data> with { length: 42, items: [1, 2, 3] }. +Create the <data> with { length: 42, items: [1, 2, 3] }. ``` If you write: ```aro -<Compute> the <len: length> from the <data>. +Compute the <len: length> from the <data>. ``` What does ARO compute? The `length` field (42) or the length of `data` (2 keys)? @@ -171,7 +171,7 @@ What does ARO compute? The `length` field (42) or the length of `data` (2 keys)? To access the `length` field, use Extract: ```aro -<Extract> the <len> from the <data: length>. +Extract the <len> from the <data: length>. ``` This returns 42—the value of the `length` field. @@ -180,8 +180,8 @@ This returns 42—the value of the `length` field. | Statement | Interpretation | Result | |-----------|---------------|--------| -| `<Compute> the <len: length> from <data>.` | Compute length of data | 2 | -| `<Extract> the <len> from <data: length>.` | Extract length field | 42 | +| `Compute the <len: length> from <data>.` | Compute length of data | 2 | +| `Extract the <len> from <data: length>.` | Extract length field | 42 | --- @@ -191,12 +191,12 @@ This returns 42—the value of the `length` field. ```aro (* Good: Clear what each variable holds *) -<Compute> the <greeting-length: length> from the <greeting>. -<Compute> the <password-hash: hash> from the <password>. +Compute the <greeting-length: length> from the <greeting>. +Compute the <password-hash: hash> from the <password>. (* Avoid: Unclear what 'len' or 'h' represent *) -<Compute> the <len: length> from the <greeting>. -<Compute> the <h: hash> from the <password>. +Compute the <len: length> from the <greeting>. +Compute the <h: hash> from the <password>. ``` **Keep object structures shallow when possible:** @@ -205,12 +205,12 @@ Deeply nested paths become hard to read and maintain. Consider flattening data s ```aro (* Hard to read *) -<Extract> the <name> from the <response: data.results.0.user.profile.name>. +Extract the <name> from the <response: data.results.0.user.profile.name>. (* Clearer with intermediate steps *) -<Extract> the <user> from the <response: data.results.0.user>. -<Extract> the <profile> from the <user: profile>. -<Extract> the <name> from the <profile: name>. +Extract the <user> from the <response: data.results.0.user>. +Extract the <profile> from the <user: profile>. +Extract the <name> from the <profile: name>. ``` **When ambiguity exists, prefer explicit actions:** @@ -219,15 +219,15 @@ If a field name collides with an operation name, use the appropriate action expl ```aro (* Explicit about intent *) -<Extract> the <len-value> from the <obj: length>. (* Get the field *) -<Compute> the <obj-size: count> from the <obj>. (* Count the keys *) +Extract the <len-value> from the <obj: length>. (* Get the field *) +Compute the <obj-size: count> from the <obj>. (* Count the keys *) ``` In summary, qualifiers serve two purposes: navigating data structures and selecting operations. ```aro -<Extract> the <city> from the <user: address.city>. -<Compute> the <name-upper: uppercase> from the <name>. +Extract the <city> from the <user: address.city>. +Compute the <name-upper: uppercase> from the <name>. ``` --- diff --git a/Book/TheLanguageGuide/Chapter10-HappyPath.md b/Book/TheLanguageGuide/Chapter10-HappyPath.md index 1ea2ddfd..8f99d177 100644 --- a/Book/TheLanguageGuide/Chapter10-HappyPath.md +++ b/Book/TheLanguageGuide/Chapter10-HappyPath.md @@ -45,9 +45,9 @@ Here is ARO code followed by the runtime error messages it produces when operati **Code:** ```aro (getUser: User API) { - <Extract> the <id> from the <pathParameters: id>. - <Retrieve> the <user> from the <user-repository> where id = <id>. - <Return> an <OK: status> with <user>. + Extract the <id> from the <pathParameters: id>. + Retrieve the <user> from the <user-repository> where id = <id>. + Return an <OK: status> with <user>. } ``` @@ -56,7 +56,7 @@ Here is ARO code followed by the runtime error messages it produces when operati Runtime Error: Cannot retrieve the user from the user-repository where id = 530 Feature: getUser Business Activity: User API - Statement: <Retrieve> the <user> from the <user-repository> where id = <id> + Statement: Retrieve the <user> from the <user-repository> where id = <id> ``` **When pathParameters does not contain id:** @@ -64,17 +64,17 @@ Runtime Error: Cannot retrieve the user from the user-repository where id = 530 Runtime Error: Cannot extract the id from the pathParameters: id Feature: getUser Business Activity: User API - Statement: <Extract> the <id> from the <pathParameters: id> + Statement: Extract the <id> from the <pathParameters: id> Cause: Key 'id' not found in pathParameters ``` **Another example with validation:** ```aro (createOrder: Order API) { - <Extract> the <data> from the <request: body>. - <Validate> the <data> against the <order-schema>. - <Store> the <order> in the <order-repository>. - <Return> a <Created: status> with <order>. + Extract the <data> from the <request: body>. + Validate the <data> against the <order-schema>. + Store the <order> in the <order-repository>. + Return a <Created: status> with <order>. } ``` @@ -83,7 +83,7 @@ Runtime Error: Cannot extract the id from the pathParameters: id Runtime Error: Cannot validate the data against the order-schema Feature: createOrder Business Activity: Order API - Statement: <Validate> the <data> against the <order-schema> + Statement: Validate the <data> against the <order-schema> Cause: Validation failed ``` @@ -92,7 +92,7 @@ Runtime Error: Cannot validate the data against the order-schema Runtime Error: Cannot store the order in the order-repository Feature: createOrder Business Activity: Order API - Statement: <Store> the <order> in the <order-repository> + Statement: Store the <order> in the <order-repository> Cause: Connection refused ``` diff --git a/Book/TheLanguageGuide/Chapter11-EventBus.md b/Book/TheLanguageGuide/Chapter11-EventBus.md index 8a78e5ad..3739f38e 100644 --- a/Book/TheLanguageGuide/Chapter11-EventBus.md +++ b/Book/TheLanguageGuide/Chapter11-EventBus.md @@ -228,30 +228,30 @@ The observer pattern is declared through business activity naming. A feature set ```aro (* Observe ALL status transitions *) (Audit Order Status: status StateObserver) { - <Extract> the <orderId> from the <transition: entityId>. - <Extract> the <fromState> from the <transition: fromState>. - <Extract> the <toState> from the <transition: toState>. + Extract the <orderId> from the <transition: entityId>. + Extract the <fromState> from the <transition: fromState>. + Extract the <toState> from the <transition: toState>. - <Log> "[AUDIT] Order ${orderId}: ${fromState} -> ${toState}" to the <console>. + Log "[AUDIT] Order ${orderId}: ${fromState} -> ${toState}" to the <console>. - <Return> an <OK: status> for the <audit>. + Return an <OK: status> for the <audit>. } (* Observe ONLY when order is placed *) (Notify Order Placed: status StateObserver<draft_to_placed>) { - <Extract> the <orderId> from the <transition: entityId>. - <Log> "Order ${orderId} has been placed!" to the <console>. - <Return> an <OK: status> for the <notification>. + Extract the <orderId> from the <transition: entityId>. + Log "Order ${orderId} has been placed!" to the <console>. + Return an <OK: status> for the <notification>. } (* Observe ONLY when order ships *) (Send Shipping Notification: status StateObserver<paid_to_shipped>) { - <Extract> the <order> from the <transition: entity>. - <Extract> the <tracking> from the <order: trackingNumber>. + Extract the <order> from the <transition: entity>. + Extract the <tracking> from the <order: trackingNumber>. - <Log> "Order shipped! Tracking: ${tracking}" to the <console>. + Log "Order shipped! Tracking: ${tracking}" to the <console>. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } ``` diff --git a/Book/TheLanguageGuide/Chapter13-CustomEvents.md b/Book/TheLanguageGuide/Chapter13-CustomEvents.md index 1ed80981..46743372 100644 --- a/Book/TheLanguageGuide/Chapter13-CustomEvents.md +++ b/Book/TheLanguageGuide/Chapter13-CustomEvents.md @@ -65,71 +65,71 @@ Here is a complete order processing saga showing event-driven choreography: ```aro (* Step 1: HTTP handler creates order and starts the saga *) (createOrder: Order API) { - <Extract> the <order-data> from the <request: body>. - <Create> the <order> with <order-data>. - <Store> the <order> in the <order-repository>. + Extract the <order-data> from the <request: body>. + Create the <order> with <order-data>. + Store the <order> in the <order-repository>. (* Emit event to start the saga *) - <Emit> an <OrderPlaced: event> with <order>. + Emit an <OrderPlaced: event> with <order>. - <Return> a <Created: status> with <order>. + Return a <Created: status> with <order>. } (* Step 2: Reserve inventory when order is placed *) (Reserve Inventory: OrderPlaced Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <items> from the <order: items>. + Extract the <order> from the <event: order>. + Extract the <items> from the <order: items>. (* Reserve each item in inventory *) - <Retrieve> the <inventory> from the <inventory-service> for <items>. - <Update> the <inventory> with { reserved: true }. - <Store> the <inventory> in the <inventory-service>. + Retrieve the <inventory> from the <inventory-service> for <items>. + Update the <inventory> with { reserved: true }. + Store the <inventory> in the <inventory-service>. (* Continue the saga *) - <Emit> an <InventoryReserved: event> with <order>. + Emit an <InventoryReserved: event> with <order>. } (* Step 3: Process payment after inventory is reserved *) (Process Payment: InventoryReserved Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <amount> from the <order: total>. - <Extract> the <payment-method> from the <order: paymentMethod>. + Extract the <order> from the <event: order>. + Extract the <amount> from the <order: total>. + Extract the <payment-method> from the <order: paymentMethod>. (* Charge the customer *) - <Send> the <charge-request> to the <payment-gateway> with { + Send the <charge-request> to the <payment-gateway> with { amount: <amount>, method: <payment-method> }. (* Continue the saga *) - <Emit> a <PaymentProcessed: event> with <order>. + Emit a <PaymentProcessed: event> with <order>. } (* Step 4: Ship order after payment succeeds *) (Ship Order: PaymentProcessed Handler) { - <Extract> the <order> from the <event: order>. + Extract the <order> from the <event: order>. (* Update order status and create shipment *) - <Update> the <order> with { status: "shipped" }. - <Store> the <order> in the <order-repository>. - <Send> the <shipment-request> to the <shipping-service> with <order>. + Update the <order> with { status: "shipped" }. + Store the <order> in the <order-repository>. + Send the <shipment-request> to the <shipping-service> with <order>. (* Final event in the happy path *) - <Emit> an <OrderShipped: event> with <order>. + Emit an <OrderShipped: event> with <order>. } (* Notification handler - runs in parallel with saga *) (Notify Customer: OrderShipped Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <email> from the <order: customerEmail>. + Extract the <order> from the <event: order>. + Extract the <email> from the <order: customerEmail>. - <Send> the <shipping-notification> to the <email-service> with { + Send the <shipping-notification> to the <email-service> with { to: <email>, template: "order-shipped", order: <order> }. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } ``` @@ -218,11 +218,11 @@ Use a PascalCase qualifier to reference the schema: ```aro (Send Welcome Email: UserCreated Handler) { (* Typed extraction - validates against UserCreatedEvent schema *) - <Extract> the <event-data: UserCreatedEvent> from the <event: data>. + Extract the <event-data: UserCreatedEvent> from the <event: data>. (* Properties are now guaranteed to exist *) - <Send> the <welcome-email> to <event-data: email>. - <Return> an <OK: status> for the <notification>. + Send the <welcome-email> to <event-data: email>. + Return an <OK: status> for the <notification>. } ``` @@ -238,13 +238,13 @@ The PascalCase qualifier (`UserCreatedEvent`) triggers schema lookup and validat ```aro (* Before: field-by-field extraction *) -<Extract> the <data> from the <event: data>. -<Extract> the <userId> from the <data: userId>. -<Extract> the <email> from the <data: email>. -<Extract> the <name> from the <data: name>. +Extract the <data> from the <event: data>. +Extract the <userId> from the <data: userId>. +Extract the <email> from the <data: email>. +Extract the <name> from the <data: name>. (* After: typed extraction *) -<Extract> the <data: UserCreatedEvent> from the <event: data>. +Extract the <data: UserCreatedEvent> from the <event: data>. (* Access properties with <data: email>, <data: name>, etc. *) ``` @@ -253,7 +253,7 @@ The PascalCase qualifier (`UserCreatedEvent`) triggers schema lookup and validat Validation errors follow ARO-0006 "Code Is The Error Message": ``` -Cannot <Extract> the <event-data: UserCreatedEvent> from the <event: data>. +Cannot Extract the <event-data: UserCreatedEvent> from the <event: data>. Schema 'UserCreatedEvent' validation failed: Missing required property 'email' Required properties: userId, email diff --git a/Book/TheLanguageGuide/Chapter14-OpenAPI.md b/Book/TheLanguageGuide/Chapter14-OpenAPI.md index 5862be27..38403750 100644 --- a/Book/TheLanguageGuide/Chapter14-OpenAPI.md +++ b/Book/TheLanguageGuide/Chapter14-OpenAPI.md @@ -70,9 +70,9 @@ After the server starts, you use the Keepalive action to keep the application ru ```aro (Application-Start: User API) { - <Log> "API starting..." to the <console>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "API starting..." to the <console>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } ``` diff --git a/Book/TheLanguageGuide/Chapter15-HTTPFeatureSets.md b/Book/TheLanguageGuide/Chapter15-HTTPFeatureSets.md index e0e66ec8..32972b3d 100644 --- a/Book/TheLanguageGuide/Chapter15-HTTPFeatureSets.md +++ b/Book/TheLanguageGuide/Chapter15-HTTPFeatureSets.md @@ -111,67 +111,67 @@ paths: ```aro (* List all items for an order *) (listOrderItems: Order API) { - <Extract> the <order-id> from the <pathParameters: orderId>. + Extract the <order-id> from the <pathParameters: orderId>. (* Verify order exists *) - <Retrieve> the <order> from the <order-repository> where id = <order-id>. + Retrieve the <order> from the <order-repository> where id = <order-id>. (* Get items for this order *) - <Retrieve> the <items> from the <item-repository> where orderId = <order-id>. + Retrieve the <items> from the <item-repository> where orderId = <order-id>. - <Return> an <OK: status> with <items>. + Return an <OK: status> with <items>. } (* Get a specific item, verifying it belongs to the order *) (getOrderItem: Order API) { - <Extract> the <order-id> from the <pathParameters: orderId>. - <Extract> the <item-id> from the <pathParameters: itemId>. + Extract the <order-id> from the <pathParameters: orderId>. + Extract the <item-id> from the <pathParameters: itemId>. (* Retrieve with both constraints to enforce ownership *) - <Retrieve> the <item> from the <item-repository> + Retrieve the <item> from the <item-repository> where id = <item-id> and orderId = <order-id>. - <Return> an <OK: status> with <item>. + Return an <OK: status> with <item>. } (* Create a new item for an order *) (createOrderItem: Order API) { - <Extract> the <order-id> from the <pathParameters: orderId>. - <Extract> the <item-data> from the <request: body>. + Extract the <order-id> from the <pathParameters: orderId>. + Extract the <item-data> from the <request: body>. (* Verify order exists before adding item *) - <Retrieve> the <order> from the <order-repository> where id = <order-id>. + Retrieve the <order> from the <order-repository> where id = <order-id>. (* Create item with parent reference *) - <Create> the <item> with { + Create the <item> with { orderId: <order-id>, productId: <item-data>.productId, quantity: <item-data>.quantity, price: <item-data>.price }. - <Store> the <item> in the <item-repository>. + Store the <item> in the <item-repository>. (* Recalculate order total *) - <Emit> an <OrderItemAdded: event> with { order: <order>, item: <item> }. + Emit an <OrderItemAdded: event> with { order: <order>, item: <item> }. - <Return> a <Created: status> with <item>. + Return a <Created: status> with <item>. } (* Delete an item from an order *) (deleteOrderItem: Order API) { - <Extract> the <order-id> from the <pathParameters: orderId>. - <Extract> the <item-id> from the <pathParameters: itemId>. + Extract the <order-id> from the <pathParameters: orderId>. + Extract the <item-id> from the <pathParameters: itemId>. (* Verify ownership before deletion *) - <Retrieve> the <item> from the <item-repository> + Retrieve the <item> from the <item-repository> where id = <item-id> and orderId = <order-id>. - <Delete> the <item> from the <item-repository>. + Delete the <item> from the <item-repository>. - <Emit> an <OrderItemRemoved: event> with { orderId: <order-id>, itemId: <item-id> }. + Emit an <OrderItemRemoved: event> with { orderId: <order-id>, itemId: <item-id> }. - <Return> a <NoContent: status> for the <deletion>. + Return a <NoContent: status> for the <deletion>. } ``` diff --git a/Book/TheLanguageGuide/Chapter17-BuiltinServices.md b/Book/TheLanguageGuide/Chapter17-BuiltinServices.md index b4ca0727..8d7a3510 100644 --- a/Book/TheLanguageGuide/Chapter17-BuiltinServices.md +++ b/Book/TheLanguageGuide/Chapter17-BuiltinServices.md @@ -53,9 +53,9 @@ The file system service provides comprehensive operations for reading, writing, Reading files uses the Read action with a file path. The action reads the file contents and binds them to a result. For JSON files, the content is parsed into a structured object. For text files, the content is a string. The path can be relative to the application directory or absolute. ```aro -<Read> the <content> from the <file: "./README.md">. -<Read> the <config: JSON> from the <file: "./config.json">. -<Read> the <image: bytes> from the <file: "./logo.png">. +Read the <content> from the <file: "./README.md">. +Read the <config: JSON> from the <file: "./config.json">. +Read the <image: bytes> from the <file: "./logo.png">. ``` ### Writing Files @@ -63,8 +63,8 @@ Reading files uses the Read action with a file path. The action reads the file c Writing files uses the Write action with data and a path. The action serializes the data and writes it to the specified location. Parent directories are created automatically if they do not exist. ```aro -<Write> the <report> to the <file: "./output/report.txt">. -<Write> the <data: JSON> to the <file: "./export.json">. +Write the <report> to the <file: "./output/report.txt">. +Write the <data: JSON> to the <file: "./export.json">. ``` ### Appending to Files @@ -72,7 +72,7 @@ Writing files uses the Write action with data and a path. The action serializes The Append action adds content to the end of an existing file, creating the file if it does not exist. ```aro -<Append> the <log-line> to the <file: "./logs/app.log">. +Append the <log-line> to the <file: "./logs/app.log">. ``` ### Checking File Existence @@ -80,10 +80,10 @@ The Append action adds content to the end of an existing file, creating the file The Exists action checks whether a file or directory exists at a given path. ```aro -<Exists> the <found> for the <file: "./config.json">. +Exists the <found> for the <file: "./config.json">. when <found> is false { - <Log> "Config not found!" to the <console>. + Log "Config not found!" to the <console>. } ``` @@ -92,9 +92,9 @@ when <found> is false { The Stat action retrieves detailed metadata about a file or directory, including size, modification dates, and permissions. ```aro -<Stat> the <info> for the <file: "./document.pdf">. -<Log> <info: size> to the <console>. -<Log> <info: modified> to the <console>. +Stat the <info> for the <file: "./document.pdf">. +Log <info: size> to the <console>. +Log <info: modified> to the <console>. ``` The result contains: name, path, size (bytes), isFile, isDirectory, created, modified, accessed, and permissions. @@ -105,16 +105,16 @@ The List action retrieves the contents of a directory. You can filter by glob pa ```aro (* List all files in a directory *) -<Create> the <uploads-path> with "./uploads". -<List> the <entries> from the <directory: uploads-path>. +Create the <uploads-path> with "./uploads". +List the <entries> from the <directory: uploads-path>. (* Filter with glob pattern *) -<Create> the <src-path> with "./src". -<List> the <aro-files> from the <directory: src-path> matching "*.aro". +Create the <src-path> with "./src". +List the <aro-files> from the <directory: src-path> matching "*.aro". (* List recursively *) -<Create> the <project-path> with "./project". -<List> the <all-files> from the <directory: project-path> recursively. +Create the <project-path> with "./project". +List the <all-files> from the <directory: project-path> recursively. ``` Each entry contains: name, path, size, isFile, isDirectory, and modified. @@ -132,8 +132,8 @@ The CreateDirectory action creates a directory, including any necessary parent d The Copy action copies a file or directory to a new location. Directory copies are recursive by default. ```aro -<Copy> the <file: "./template.txt"> to the <destination: "./copy.txt">. -<Copy> the <directory: "./src"> to the <destination: "./backup/src">. +Copy the <file: "./template.txt"> to the <destination: "./copy.txt">. +Copy the <directory: "./src"> to the <destination: "./backup/src">. ``` ### Moving and Renaming @@ -141,8 +141,8 @@ The Copy action copies a file or directory to a new location. Directory copies a The Move action moves or renames a file or directory. ```aro -<Move> the <file: "./draft.txt"> to the <destination: "./final.txt">. -<Move> the <file: "./inbox/report.pdf"> to the <destination: "./archive/report.pdf">. +Move the <file: "./draft.txt"> to the <destination: "./final.txt">. +Move the <file: "./inbox/report.pdf"> to the <destination: "./archive/report.pdf">. ``` ### Deleting Files @@ -150,7 +150,7 @@ The Move action moves or renames a file or directory. The Delete action removes a file from the file system. ```aro -<Delete> the <file: "./temp/cache.json">. +Delete the <file: "./temp/cache.json">. ``` ### File Watching @@ -158,7 +158,7 @@ The Delete action removes a file from the file system. File watching monitors a directory for changes and emits events when files are created, modified, or deleted. You start watching during Application-Start by specifying the directory to monitor. When changes occur, the runtime emits File Event events that your handlers can process. This is useful for applications that need to react to external file changes—configuration reloading, data import, file synchronization. ```aro -<Start> the <file-monitor> with "./data". +Start the <file-monitor> with "./data". ``` Event handlers are named according to the event type: `Handle File Created`, `Handle File Modified`, or `Handle File Deleted`. @@ -219,48 +219,48 @@ Here is a complete example demonstrating multiple built-in services working toge (* Config Monitor - Watch files and report changes via HTTP *) (Application-Start: Config Monitor) { - <Log> "Starting configuration monitor..." to the <console>. + Log "Starting configuration monitor..." to the <console>. (* Load the monitoring endpoint from environment or config *) - <Create> the <webhook-url> with "https://monitoring.example.com/webhook". + Create the <webhook-url> with "https://monitoring.example.com/webhook". (* Start watching the config directory *) - <Start> the <file-monitor> with "./config". + Start the <file-monitor> with "./config". - <Log> "Watching ./config for changes..." to the <console>. + Log "Watching ./config for changes..." to the <console>. (* Keep running until shutdown signal *) - <Keepalive> the <application> for the <events>. + Keepalive the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } (Report Config Change: File Event Handler) { (* Extract the changed file path *) - <Extract> the <path> from the <event: path>. - <Extract> the <event-type> from the <event: type>. + Extract the <path> from the <event: path>. + Extract the <event-type> from the <event: type>. - <Log> "Config changed:" to the <console>. - <Log> <path> to the <console>. + Log "Config changed:" to the <console>. + Log <path> to the <console>. (* Build notification payload *) - <Create> the <notification> with { + Create the <notification> with { file: <path>, change: <event-type>, timestamp: "now" }. (* Send to monitoring webhook *) - <Send> <notification> to the <webhook-url>. + Send <notification> to the <webhook-url>. - <Log> "Change reported to monitoring service." to the <console>. + Log "Change reported to monitoring service." to the <console>. - <Return> an <OK: status> for the <event>. + Return an <OK: status> for the <event>. } (Application-End: Success) { - <Log> "Config monitor stopped." to the <console>. - <Return> an <OK: status> for the <shutdown>. + Log "Config monitor stopped." to the <console>. + Return an <OK: status> for the <shutdown>. } ``` diff --git a/Book/TheLanguageGuide/Chapter18-FormatAwareIO.md b/Book/TheLanguageGuide/Chapter18-FormatAwareIO.md index c4e8fe3d..3a540f3d 100644 --- a/Book/TheLanguageGuide/Chapter18-FormatAwareIO.md +++ b/Book/TheLanguageGuide/Chapter18-FormatAwareIO.md @@ -50,9 +50,9 @@ The file extension is the key. Write to `users.json` and get JSON. Write to `use ```aro (* Same data, three different formats *) -<Write> the <users> to "./output/users.json". -<Write> the <users> to "./output/users.csv". -<Write> the <users> to "./output/users.yaml". +Write the <users> to "./output/users.json". +Write the <users> to "./output/users.csv". +Write the <users> to "./output/users.yaml". ``` This pattern follows ARO's philosophy of reducing ceremony. The file path already tells you the intended format. Making you specify it again would be redundant. @@ -91,12 +91,12 @@ The Write action serializes your data according to the file extension. Each form JSON is the most common format for structured data. ARO produces pretty-printed JSON with sorted keys for consistency and readability. ```aro -<Create> the <users> with [ +Create the <users> with [ { "id": 1, "name": "Alice", "email": "alice@example.com" }, { "id": 2, "name": "Bob", "email": "bob@example.com" } ]. -<Write> the <users> to "./output/users.json". +Write the <users> to "./output/users.json". ``` **Output (users.json):** @@ -118,7 +118,7 @@ JSON is the most common format for structured data. ARO produces pretty-printed JSON Lines (`.jsonl` or `.ndjson`) writes one JSON object per line with no extra whitespace. This format is ideal for streaming and logging because each line is independently parseable. ```aro -<Write> the <events> to "./logs/events.jsonl". +Write the <events> to "./logs/events.jsonl". ``` **Output (events.jsonl):** @@ -132,7 +132,7 @@ JSON Lines (`.jsonl` or `.ndjson`) writes one JSON object per line with no extra YAML produces human-readable output that is easy to edit by hand. It uses indentation to show structure and avoids the visual noise of brackets and quotes. ```aro -<Write> the <config> to "./settings.yaml". +Write the <config> to "./settings.yaml". ``` **Output (settings.yaml):** @@ -148,7 +148,7 @@ YAML produces human-readable output that is easy to edit by hand. It uses indent TOML is similar but uses explicit section headers. It is particularly popular for application configuration files. ```aro -<Write> the <users> to "./config/users.toml". +Write the <users> to "./config/users.toml". ``` **Output (users.toml):** @@ -169,7 +169,7 @@ email = "bob@example.com" Comma-separated values (CSV) is the universal format for spreadsheet data. ARO writes a header row with field names, followed by data rows. ```aro -<Write> the <report> to "./export/report.csv". +Write the <report> to "./export/report.csv". ``` **Output (report.csv):** @@ -188,7 +188,7 @@ Values containing the delimiter character, quotes, or newlines are automatically XML output uses the variable name from your Write statement as the root element. This provides meaningful document structure without requiring additional configuration. ```aro -<Write> the <users> to "./data/users.xml". +Write the <users> to "./data/users.xml". ``` **Output (users.xml):** @@ -215,8 +215,8 @@ Notice how `<users>` becomes the root element because that was the variable name Markdown produces pipe-delimited tables suitable for documentation. HTML produces properly structured tables with thead and tbody elements. ```aro -<Write> the <summary> to "./docs/summary.md". -<Write> the <report> to "./output/report.html". +Write the <summary> to "./docs/summary.md". +Write the <report> to "./output/report.html". ``` **Markdown output:** @@ -232,7 +232,7 @@ Markdown produces pipe-delimited tables suitable for documentation. HTML produce SQL output produces INSERT statements for database migration or backup. The table name comes from the variable name. ```aro -<Write> the <users> to "./backup/users.sql". +Write the <users> to "./backup/users.sql". ``` **Output (users.sql):** @@ -248,8 +248,8 @@ String values are properly escaped to prevent SQL injection in the output. Log output produces date-prefixed entries, ideal for application logs and audit trails. Each entry receives an ISO8601 timestamp. ```aro -<Write> the <message> to "./app.log" with "Server started". -<Append> the <entry> to "./app.log" with "User logged in". +Write the <message> to "./app.log" with "Server started". +Append the <entry> to "./app.log" with "User logged in". ``` **Output (app.log):** @@ -261,8 +261,8 @@ Log output produces date-prefixed entries, ideal for application logs and audit When writing an array, each element becomes a separate log entry: ```aro -<Create> the <events> with ["Startup complete", "Listening on port 8080"]. -<Write> the <events> to "./events.log". +Create the <events> with ["Startup complete", "Listening on port 8080"]. +Write the <events> to "./events.log". ``` **Output:** @@ -276,11 +276,11 @@ When writing an array, each element becomes a separate log entry: Environment files use KEY=VALUE format with uppercase keys. Nested objects are flattened with underscore separators. ```aro -<Create> the <config> with { +Create the <config> with { "database": { "host": "localhost", "port": 5432 }, "apiKey": "secret123" }. -<Write> the <config> to "./.env". +Write the <config> to "./.env". ``` **Output (.env):** @@ -293,7 +293,7 @@ DATABASE_PORT=5432 Environment files can also be read back: ```aro -<Read> the <settings> from "./.env". +Read the <settings> from "./.env". (* Returns { "API_KEY": "secret123", "DATABASE_HOST": "localhost", ... } *) ``` @@ -302,8 +302,8 @@ Environment files can also be read back: Plain text output produces key=value pairs, one per line. Nested objects use dot notation. ```aro -<Create> the <config> with { "host": "localhost", "port": 8080, "debug": true }. -<Write> the <config> to "./output/config.txt". +Create the <config> with { "host": "localhost", "port": 8080, "debug": true }. +Write the <config> to "./output/config.txt". ``` **Output (config.txt):** @@ -359,16 +359,16 @@ Reading files reverses the process. ARO examines the file extension and parses t ```aro (* JSON becomes object or array *) -<Read> the <config> from "./settings.json". +Read the <config> from "./settings.json". (* JSONL becomes array of objects *) -<Read> the <events> from "./logs/events.jsonl". +Read the <events> from "./logs/events.jsonl". (* CSV becomes array with headers as keys *) -<Read> the <records> from "./data.csv". +Read the <records> from "./data.csv". (* YAML becomes object or array *) -<Read> the <settings> from "./config.yaml". +Read the <settings> from "./config.yaml". ``` Each format parses to an appropriate data structure: @@ -392,10 +392,10 @@ Sometimes you want to read a file as raw text without parsing. Use the `String` ```aro (* Parse JSON to structured data *) -<Read> the <config> from "./settings.json". +Read the <config> from "./settings.json". (* Read raw JSON as string - no parsing *) -<Read> the <raw-json: String> from "./settings.json". +Read the <raw-json: String> from "./settings.json". ``` This is useful when you need to inspect the raw content or pass it to an external system without modification. @@ -417,7 +417,7 @@ CSV and TSV formats support additional configuration options. These options cont Some systems use semicolons or other characters as field separators: ```aro -<Write> the <data> to "./export.csv" with { delimiter: ";" }. +Write the <data> to "./export.csv" with { delimiter: ";" }. ``` ### Header Row Control @@ -425,13 +425,13 @@ Some systems use semicolons or other characters as field separators: You can suppress the header row when writing: ```aro -<Write> the <data> to "./export.csv" with { header: false }. +Write the <data> to "./export.csv" with { header: false }. ``` When reading, if your CSV has no header row, specify this so the parser knows to treat the first line as data: ```aro -<Read> the <data> from "./import.csv" with { header: false }. +Read the <data> from "./import.csv" with { header: false }. ``` --- @@ -445,18 +445,18 @@ A common pattern is reading data from one format and writing to another. ARO mak ```aro (Application-Start: Data Transformer) { (* Read from CSV *) - <Read> the <records> from "./input/data.csv". + Read the <records> from "./input/data.csv". (* Process the data *) - <Log> "Processing records..." to the <console>. + Log "Processing records..." to the <console>. (* Write to multiple formats *) - <Write> the <records> to "./output/data.json". - <Write> the <records> to "./output/data.yaml". - <Write> the <records> to "./output/report.md". + Write the <records> to "./output/data.json". + Write the <records> to "./output/data.yaml". + Write the <records> to "./output/report.md". - <Log> "Transformation complete!" to the <console>. - <Return> an <OK: status> for the <transform>. + Log "Transformation complete!" to the <console>. + Return an <OK: status> for the <transform>. } ``` @@ -466,21 +466,21 @@ When you need to provide data in multiple formats for different consumers: ```aro (exportData: Export API) { - <Retrieve> the <users> from the <user-repository>. + Retrieve the <users> from the <user-repository>. (* Web API consumers get JSON *) - <Write> the <users> to "./export/users.json". + Write the <users> to "./export/users.json". (* Analysts get CSV for spreadsheets *) - <Write> the <users> to "./export/users.csv". + Write the <users> to "./export/users.csv". (* Documentation gets Markdown *) - <Write> the <users> to "./docs/users.md". + Write the <users> to "./docs/users.md". (* Archive gets SQL for database restore *) - <Write> the <users> to "./backup/users.sql". + Write the <users> to "./backup/users.sql". - <Return> an <OK: status> with "Exported to 4 formats". + Return an <OK: status> with "Exported to 4 formats". } ``` @@ -525,8 +525,8 @@ While format-aware I/O handles file serialization, web applications often need t The `links` specifier extracts all `href` attributes from anchor tags: ```aro -<Request> the <html> from "https://example.com". -<ParseHtml> the <links: links> from the <html>. +Request the <html> from "https://example.com". +ParseHtml the <links: links> from the <html>. (* Result: ["/about", "/contact", "https://external.com", ...] *) ``` @@ -538,13 +538,13 @@ This is essential for web crawlers and link validation tools. The `content` specifier returns a structured object with the page title and cleaned body text: ```aro -<Request> the <html> from "https://example.com/article". -<ParseHtml> the <page: content> from the <html>. -<Extract> the <title> from the <page: title>. -<Extract> the <body-text> from the <page: content>. +Request the <html> from "https://example.com/article". +ParseHtml the <page: content> from the <html>. +Extract the <title> from the <page: title>. +Extract the <body-text> from the <page: content>. -<Log> <title> to the <console>. -<Log> <body-text> to the <console>. +Log <title> to the <console>. +Log <body-text> to the <console>. ``` The action intelligently extracts content from `<main>`, `<article>`, or `<body>` elements and normalizes whitespace. @@ -555,16 +555,16 @@ The `<ParseHtml>` action pairs naturally with `<Request>` for web scraping workf ```aro (Fetch Article: Scraper) { - <Request> the <html> from <article-url>. + Request the <html> from <article-url>. (* Extract both links and content *) - <ParseHtml> the <links: links> from the <html>. - <ParseHtml> the <article: content> from the <html>. + ParseHtml the <links: links> from the <html>. + ParseHtml the <article: content> from the <html>. (* Save the extracted content *) - <Write> the <article> to "./output/article.json". + Write the <article> to "./output/article.json". - <Return> an <OK: status> with { + Return an <OK: status> with { links: <links>, title: <article: title> }. @@ -576,13 +576,13 @@ The `<ParseHtml>` action pairs naturally with `<Request>` for web scraping workf The `markdown` specifier converts HTML to structured Markdown, preserving document structure including headings, links, tables, lists, and formatting: ```aro -<Request> the <html> from "https://example.com/article". -<ParseHtml> the <result: markdown> from the <html>. -<Extract> the <title> from the <result: title>. -<Extract> the <markdown-content> from the <result: markdown>. +Request the <html> from "https://example.com/article". +ParseHtml the <result: markdown> from the <html>. +Extract the <title> from the <result: title>. +Extract the <markdown-content> from the <result: markdown>. (* Save as markdown file *) -<Write> the <markdown-content> to "./output/article.md". +Write the <markdown-content> to "./output/article.md". ``` This is useful for: diff --git a/Book/TheLanguageGuide/Chapter19-SystemObjects.md b/Book/TheLanguageGuide/Chapter19-SystemObjects.md index 5ba15b0b..7a23112f 100644 --- a/Book/TheLanguageGuide/Chapter19-SystemObjects.md +++ b/Book/TheLanguageGuide/Chapter19-SystemObjects.md @@ -148,9 +148,9 @@ For sink operations, ARO provides a clean, intuitive syntax where the value come ```aro (* Sink syntax - direct value to system object *) -<Log> "Hello, World!" to the <console>. -<Log> <data> to the <console>. -<Log> { status: "ok", count: 42 } to the <console>. +Log "Hello, World!" to the <console>. +Log <data> to the <console>. +Log { status: "ok", count: 42 } to the <console>. ``` Sink verbs that support this syntax include: @@ -174,19 +174,19 @@ ARO provides three console-related system objects: ```aro (* Write to console (stdout) *) -<Log> "Starting server..." to the <console>. +Log "Starting server..." to the <console>. (* Write to console stdout (explicit) *) -<Log> "Processing data..." to the <console: output>. +Log "Processing data..." to the <console: output>. (* Write to console stderr *) -<Log> "Warning: config missing" to the <console: error>. +Log "Warning: config missing" to the <console: error>. (* Write to stderr object (alternative syntax) *) -<Log> "Error message" to the <stderr>. +Log "Error message" to the <stderr>. (* Read from stdin *) -<Read> the <input> from the <stdin>. +Read the <input> from the <stdin>. ``` **Console Output Streams:** @@ -321,10 +321,10 @@ The `env` system object provides access to environment variables: ```aro (* Read a specific environment variable *) -<Extract> the <api-key> from the <env: API_KEY>. +Extract the <api-key> from the <env: API_KEY>. (* Read all environment variables *) -<Extract> the <all-vars> from the <env>. +Extract the <all-vars> from the <env>. ``` ### Command-Line Parameters @@ -333,11 +333,11 @@ The `parameter` system object provides access to command-line arguments passed t ```aro (* Read a specific parameter *) -<Extract> the <url> from the <parameter: url>. -<Extract> the <count> from the <parameter: count>. +Extract the <url> from the <parameter: url>. +Extract the <count> from the <parameter: count>. (* Read all parameters as a dictionary *) -<Extract> the <all-params> from the <parameter>. +Extract the <all-params> from the <parameter>. ``` **Passing Parameters:** @@ -375,13 +375,13 @@ Parameter values are automatically converted to appropriate types: ```aro (Application-Start: Greeter) { - <Extract> the <name> from the <parameter: name>. - <Extract> the <count> from the <parameter: count>. + Extract the <name> from the <parameter: name>. + Extract the <count> from the <parameter: count>. - <Log> "Hello, ${<name>}!" to the <console>. - <Log> "Count: ${<count>}" to the <console>. + Log "Hello, ${<name>}!" to the <console>. + Log "Count: ${<count>}" to the <console>. - <Return> an <OK: status> with <name>. + Return an <OK: status> with <name>. } ``` @@ -397,10 +397,10 @@ The `file` system object provides bidirectional file I/O with automatic format d ```aro (* Read from a file *) -<Read> the <config> from the <file: "./config.json">. +Read the <config> from the <file: "./config.json">. (* Write to a file *) -<Write> <data> to the <file: "./output.json">. +Write <data> to the <file: "./output.json">. ``` The file object automatically detects the format based on file extension and serializes/deserializes accordingly. See Chapter 16B for details on format-aware I/O. @@ -422,21 +422,21 @@ When handling HTTP requests, ARO provides context-specific system objects: ```aro (getUser: User API) { (* Access path parameters *) - <Extract> the <id> from the <pathParameters: id>. + Extract the <id> from the <pathParameters: id>. (* Access query parameters *) - <Extract> the <limit> from the <queryParameters: limit>. + Extract the <limit> from the <queryParameters: limit>. (* Access headers *) - <Extract> the <auth> from the <headers: Authorization>. + Extract the <auth> from the <headers: Authorization>. (* Access request body *) - <Extract> the <data> from the <body>. + Extract the <data> from the <body>. (* Access full request properties *) - <Extract> the <method> from the <request: method>. + Extract the <method> from the <request: method>. - <Return> an <OK: status> with <user>. + Return an <OK: status> with <user>. } ``` @@ -455,15 +455,15 @@ Event handlers have access to event-specific system objects: ```aro (Send Email: UserCreated Handler) { - <Extract> the <user> from the <event: user>. - <Send> the <welcome-email> to the <user: email>. - <Return> an <OK: status> for the <notification>. + Extract the <user> from the <event: user>. + Send the <welcome-email> to the <user: email>. + Return an <OK: status> for the <notification>. } (Application-End: Success) { - <Extract> the <reason> from the <shutdown: reason>. - <Log> <reason> to the <console>. - <Return> an <OK: status> for the <shutdown>. + Extract the <reason> from the <shutdown: reason>. + Log <reason> to the <console>. + Return an <OK: status> for the <shutdown>. } ``` @@ -480,9 +480,9 @@ Socket handlers have access to connection-related system objects: ```aro (Echo Server: Socket Event Handler) { - <Extract> the <data> from the <packet>. - <Send> <data> to the <connection>. - <Return> an <OK: status> for the <echo>. + Extract the <data> from the <packet>. + Send <data> to the <connection>. + Return an <OK: status> for the <echo>. } ``` @@ -508,16 +508,16 @@ When an ARO application has an `openapi.yaml` file, the `Contract` magic object ```aro (Application-Start: Order Service) { (* Start HTTP server using Contract configuration *) - <Start> the <http-server> with <Contract>. + Start the <http-server> with <Contract>. (* Access Contract properties *) - <Log> <Contract.http-server.port> to the <console>. - <Log> <Contract.http-server.routes> to the <console>. + Log <Contract.http-server.port> to the <console>. + Log <Contract.http-server.routes> to the <console>. (* Shorthand: <http-server> resolves to Contract.http-server *) - <Log> <http-server.port> to the <console>. + Log <http-server.port> to the <console>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` @@ -534,8 +534,8 @@ Plugins can provide custom system objects that integrate seamlessly with ARO's s ```aro (* Plugin-provided Redis system object *) -<Get> the <session> from the <redis: "session:123">. -<Set> <userData> to the <redis: "user:456">. +Get the <session> from the <redis: "session:123">. +Set <userData> to the <redis: "user:456">. ``` See Chapter 18 for details on creating plugins that provide system objects. @@ -551,7 +551,7 @@ System objects provide a unified interface for interacting with external resourc - **Bidirectional**: `file`, `connection` - **Magic Objects**: `Contract`, `now` -The sink syntax (`<Log> "message" to the <console>`) provides a clean, intuitive way to write to system objects. +The sink syntax (`Log "message" to the <console>`) provides a clean, intuitive way to write to system objects. --- diff --git a/Book/TheLanguageGuide/Chapter20-CustomActions.md b/Book/TheLanguageGuide/Chapter20-CustomActions.md index 132f15f1..5888a6b8 100644 --- a/Book/TheLanguageGuide/Chapter20-CustomActions.md +++ b/Book/TheLanguageGuide/Chapter20-CustomActions.md @@ -28,12 +28,12 @@ ARO provides two extension mechanisms: | Mechanism | What It Adds | Syntax | Best For | |-----------|--------------|--------|----------| -| **Custom Actions** | New verbs | `<Geocode> the <coords> from <addr>.` | Domain-specific operations | -| **Custom Services** | External integrations | `<Call> from <postgres: query>` | Systems with multiple methods | +| **Custom Actions** | New verbs | `Geocode the <coords> from <addr>.` | Domain-specific operations | +| **Custom Services** | External integrations | `Call from <postgres: query>` | Systems with multiple methods | -Custom actions, covered in this chapter, let you add new verbs to the language. When you implement a custom action, you can write statements like `<Geocode> the <coordinates> from the <address>` that feel native to ARO. +Custom actions, covered in this chapter, let you add new verbs to the language. When you implement a custom action, you can write statements like `Geocode the <coordinates> from the <address>` that feel native to ARO. -Custom services, covered in Chapter 20, let you integrate external systems through the `Call` action. Services provide multiple methods under a single service name: `<Call> from <postgres: query>`, `<Call> from <postgres: insert>`. +Custom services, covered in Chapter 20, let you integrate external systems through the `Call` action. Services provide multiple methods under a single service name: `Call from <postgres: query>`, `Call from <postgres: insert>`. Plugins, covered in Chapter 21, let you package and share both actions and services with the community. diff --git a/Book/TheLanguageGuide/Chapter21-CustomServices.md b/Book/TheLanguageGuide/Chapter21-CustomServices.md index 95579561..c12b7e59 100644 --- a/Book/TheLanguageGuide/Chapter21-CustomServices.md +++ b/Book/TheLanguageGuide/Chapter21-CustomServices.md @@ -8,26 +8,26 @@ Before diving into custom services, it is essential to understand how they differ from custom actions. This distinction shapes how you design extensions to ARO. -**Custom Actions** add new verbs to the language. When you create a custom action, you define a new way of expressing intent. The Geocode action lets you write `<Geocode> the <coordinates> from the <address>`. The verb "Geocode" becomes part of your ARO vocabulary. +**Custom Actions** add new verbs to the language. When you create a custom action, you define a new way of expressing intent. The Geocode action lets you write `Geocode the <coordinates> from the <address>`. The verb "Geocode" becomes part of your ARO vocabulary. -**Custom Services** are external integrations invoked through the `<Call>` action. Services do not add new verbs—they add new capabilities accessible through the existing Call verb. You write `<Call> the <result> from the <postgres: query>` to invoke the postgres service's query method. +**Custom Services** are external integrations invoked through the `<Call>` action. Services do not add new verbs—they add new capabilities accessible through the existing Call verb. You write `Call the <result> from the <postgres: query>` to invoke the postgres service's query method. The pattern reveals the distinction: ```aro (* Custom Action - new verb *) -<Geocode> the <coordinates> from the <address>. +Geocode the <coordinates> from the <address>. (* Custom Service - Call verb with service:method *) -<Call> the <users> from the <postgres: query> with { sql: "SELECT * FROM users" }. +Call the <users> from the <postgres: query> with { sql: "SELECT * FROM users" }. ``` ### When to Use Each | Use Case | Choose | Why | |----------|--------|-----| -| Domain-specific operation that feels like a language feature | Action | Reads naturally: `<Validate> the <order>` | -| External system integration (database, queue, API) | Service | Uniform pattern: `<Call> from <service: method>` | +| Domain-specific operation that feels like a language feature | Action | Reads naturally: `Validate the <order>` | +| External system integration (database, queue, API) | Service | Uniform pattern: `Call from <service: method>` | | Reusable across many projects | Service | Services are more portable | | Single, focused operation | Action | Cleaner syntax for one thing | | Multiple related operations | Service | One service, many methods | @@ -175,35 +175,35 @@ Once registered, your service is available through the Call action: ```aro (List Active Users: User Management) { - <Call> the <users> from the <postgres: query> with { + Call the <users> from the <postgres: query> with { sql: "SELECT * FROM users WHERE active = true" }. - <Return> an <OK: status> with <users>. + Return an <OK: status> with <users>. } (Create User: User Management) { - <Extract> the <data> from the <request: body>. + Extract the <data> from the <request: body>. - <Call> the <result> from the <postgres: insert> with { + Call the <result> from the <postgres: insert> with { table: "users", data: <data> }. - <Extract> the <id> from the <result: id>. - <Return> a <Created: status> with { id: <id> }. + Extract the <id> from the <result: id>. + Return a <Created: status> with { id: <id> }. } (Update User Status: User Management) { - <Extract> the <id> from the <pathParameters: id>. - <Extract> the <status> from the <request: status>. + Extract the <id> from the <pathParameters: id>. + Extract the <status> from the <request: status>. - <Call> the <result> from the <postgres: execute> with { + Call the <result> from the <postgres: execute> with { sql: "UPDATE users SET status = $1 WHERE id = $2", params: [<status>, <id>] }. - <Return> an <OK: status> for the <update>. + Return an <OK: status> for the <update>. } ``` @@ -342,30 +342,30 @@ public struct RedisService: AROService { ```aro (Cache User: Caching) { - <Extract> the <user-id> from the <user: id>. + Extract the <user-id> from the <user: id>. - <Call> the <result> from the <redis: set> with { + Call the <result> from the <redis: set> with { key: "user:" + <user-id>, value: <user> }. (* Set expiration to 1 hour *) - <Call> the <expire-result> from the <redis: expire> with { + Call the <expire-result> from the <redis: expire> with { key: "user:" + <user-id>, seconds: 3600 }. - <Return> an <OK: status> for the <cache>. + Return an <OK: status> for the <cache>. } (Get Cached User: Caching) { - <Extract> the <user-id> from the <request: id>. + Extract the <user-id> from the <request: id>. - <Call> the <cached> from the <redis: get> with { + Call the <cached> from the <redis: get> with { key: "user:" + <user-id> }. - <Return> an <OK: status> with <cached>. + Return an <OK: status> with <cached>. } ``` @@ -393,21 +393,21 @@ Some capabilities in ARO are implemented as built-in actions rather than service ```aro (* Built-in Request action - NOT a service *) -<Request> the <weather> from "https://api.weather.com/current". +Request the <weather> from "https://api.weather.com/current". (* Service call pattern - for external integrations *) -<Call> the <users> from the <postgres: query> with { sql: "..." }. +Call the <users> from the <postgres: query> with { sql: "..." }. ``` The distinction: built-in actions are part of the ARO language and have dedicated syntax. Services are external integrations that share the uniform Call pattern. | Capability | Implementation | Syntax | |------------|----------------|--------| -| HTTP requests | Built-in action | `<Request> the <data> from <url>.` | -| File operations | Built-in action | `<Read> the <data> from <path>.` | -| Database queries | Custom service | `<Call> from <postgres: query>` | -| Message queues | Custom service | `<Call> from <rabbitmq: publish>` | -| Cloud storage | Custom service | `<Call> from <s3: upload>` | +| HTTP requests | Built-in action | `Request the <data> from <url>.` | +| File operations | Built-in action | `Read the <data> from <path>.` | +| Database queries | Custom service | `Call from <postgres: query>` | +| Message queues | Custom service | `Call from <rabbitmq: publish>` | +| Cloud storage | Custom service | `Call from <s3: upload>` | --- diff --git a/Book/TheLanguageGuide/Chapter22-Plugins.md b/Book/TheLanguageGuide/Chapter22-Plugins.md index 698b13a7..83f9b6ea 100644 --- a/Book/TheLanguageGuide/Chapter22-Plugins.md +++ b/Book/TheLanguageGuide/Chapter22-Plugins.md @@ -22,8 +22,8 @@ A plugin can contain: | Type | Adds | Invocation Pattern | Example | |------|------|-------------------|---------| -| **Actions** | New verbs | `<Verb> the <result> from <object>.` | `<Geocode> the <coords> from <address>.` | -| **Services** | External integrations | `<Call> from <service: method>` | `<Call> from <zip: compress>` | +| **Actions** | New verbs | `<Verb> the <result> from <object>.` | `Geocode the <coords> from <address>.` | +| **Services** | External integrations | `Call from <service: method>` | `Call from <zip: compress>` | | **Feature Sets** | Reusable business logic | Triggered by events | `FormatCSV`, `SendNotification` | --- @@ -161,23 +161,23 @@ provides: ```aro (* FormatTitle — Capitalize first letter of each word *) (FormatTitle: String Operations) { - <Extract> the <text> from the <input: text>. - <Transform> the <title> from <text> using <titlecase>. - <Return> an <OK: status> with <title>. + Extract the <text> from the <input: text>. + Transform the <title> from <text> using <titlecase>. + Return an <OK: status> with <title>. } (* TruncateText — Shorten text with ellipsis *) (TruncateText: String Operations) { - <Extract> the <text> from the <input: text>. - <Extract> the <max-length> from the <input: maxLength>. - <Compute> the <length: length> from <text>. + Extract the <text> from the <input: text>. + Extract the <max-length> from the <input: maxLength>. + Compute the <length: length> from <text>. when <length> > <max-length> { - <Transform> the <truncated> from <text> using <substring: 0> to <max-length>. - <Create> the <result> with <truncated> + "...". + Transform the <truncated> from <text> using <substring: 0> to <max-length>. + Create the <result> with <truncated> + "...". } else { - <Create> the <result> with <text>. + Create the <result> with <text>. } - <Return> an <OK: status> with <result>. + Return an <OK: status> with <result>. } ``` @@ -186,9 +186,9 @@ Feature sets from plugins are automatically available in your application with a ```aro (* Use plugin feature set *) (Format User Name: User Processing) { - <Extract> the <name> from the <user: fullName>. - <Emit> a <FormatTitle: event> with { text: <name> }. - <Return> an <OK: status> with <name>. + Extract the <name> from the <user: fullName>. + Emit a <FormatTitle: event> with { text: <name> }. + Return an <OK: status> with <name>. } ``` @@ -269,7 +269,7 @@ public func registerPlugin() { **Usage:** ```aro -<Geocode> the <coordinates> from the <address>. +Geocode the <coordinates> from the <address>. ``` --- diff --git a/Book/TheLanguageGuide/Chapter24-MultiFile.md b/Book/TheLanguageGuide/Chapter24-MultiFile.md index 693ae5f6..b7e1bab3 100644 --- a/Book/TheLanguageGuide/Chapter24-MultiFile.md +++ b/Book/TheLanguageGuide/Chapter24-MultiFile.md @@ -90,65 +90,65 @@ ecommerce-api/ **main.aro** — Lifecycle only, no business logic: ```aro (Application-Start: E-commerce API) { - <Log> "Starting e-commerce API..." to the <console>. - <Start> the <http-server> on port 8080. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "Starting e-commerce API..." to the <console>. + Start the <http-server> on port 8080. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } (Application-End: Success) { - <Stop> the <http-server>. - <Log> "E-commerce API stopped." to the <console>. - <Return> an <OK: status> for the <shutdown>. + Stop the <http-server>. + Log "E-commerce API stopped." to the <console>. + Return an <OK: status> for the <shutdown>. } ``` **products/products.aro** — Product domain: ```aro (listProducts: Product API) { - <Retrieve> the <products> from the <product-repository>. - <Return> an <OK: status> with <products>. + Retrieve the <products> from the <product-repository>. + Return an <OK: status> with <products>. } (getProduct: Product API) { - <Extract> the <id> from the <pathParameters: id>. - <Retrieve> the <product> from the <product-repository> where id = <id>. - <Return> an <OK: status> with <product>. + Extract the <id> from the <pathParameters: id>. + Retrieve the <product> from the <product-repository> where id = <id>. + Return an <OK: status> with <product>. } ``` **orders/orders.aro** — Order domain: ```aro (createOrder: Order API) { - <Extract> the <order-data> from the <request: body>. - <Create> the <order> with <order-data>. - <Store> the <order> in the <order-repository>. - <Emit> an <OrderPlaced: event> with <order>. - <Return> a <Created: status> with <order>. + Extract the <order-data> from the <request: body>. + Create the <order> with <order-data>. + Store the <order> in the <order-repository>. + Emit an <OrderPlaced: event> with <order>. + Return a <Created: status> with <order>. } ``` **orders/order-events.aro** — Separated event handlers: ```aro (Reserve Stock: OrderPlaced Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <items> from the <order: items>. - <Update> the <inventory> for <items> with { reserved: true }. - <Emit> an <StockReserved: event> with <order>. + Extract the <order> from the <event: order>. + Extract the <items> from the <order: items>. + Update the <inventory> for <items> with { reserved: true }. + Emit an <StockReserved: event> with <order>. } ``` **notifications/notifications.aro** — Cross-domain event handlers: ```aro (Send Order Confirmation: OrderPlaced Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <email> from the <order: customerEmail>. - <Send> the <confirmation-email> to the <email-service> with { + Extract the <order> from the <event: order>. + Extract the <email> from the <order: customerEmail>. + Send the <confirmation-email> to the <email-service> with { to: <email>, template: "order-confirmation", order: <order> }. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } ``` diff --git a/Book/TheLanguageGuide/Chapter26-StateMachines.md b/Book/TheLanguageGuide/Chapter26-StateMachines.md index 0f47b19a..18234a59 100644 --- a/Book/TheLanguageGuide/Chapter26-StateMachines.md +++ b/Book/TheLanguageGuide/Chapter26-StateMachines.md @@ -119,7 +119,7 @@ The `Accept` action validates and applies state transitions. It checks that an o The syntax uses the `_to_` separator to specify the transition: ```aro -<Accept> the <transition: from_to_target> on <object: field>. +Accept the <transition: from_to_target> on <object: field>. ``` The transition specifier contains both states separated by `_to_`. The object specifier identifies which entity and which field to examine and update. @@ -127,7 +127,7 @@ The transition specifier contains both states separated by `_to_`. The object sp Here is a concrete example that transitions an order from draft to placed: ```aro -<Accept> the <transition: draft_to_placed> on <order: status>. +Accept the <transition: draft_to_placed> on <order: status>. ``` This statement does three things: @@ -258,23 +258,23 @@ Now the ARO feature sets that implement these transitions: ```aro (* Create a new order in draft state *) (createOrder: Order Management) { - <Extract> the <data> from the <request: body>. - <Create> the <order: Order> with <data>. - <Update> the <order: status> with "draft". - <Store> the <order> into the <order-repository>. - <Return> a <Created: status> with <order>. + Extract the <data> from the <request: body>. + Create the <order: Order> with <data>. + Update the <order: status> with "draft". + Store the <order> into the <order-repository>. + Return a <Created: status> with <order>. } (* Place an order - transitions from draft to placed *) (placeOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: draft_to_placed> on <order: status>. + Accept the <transition: draft_to_placed> on <order: status>. - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } ``` @@ -285,43 +285,43 @@ The remaining transitions follow the same pattern: ```aro (* Pay for an order - transitions from placed to paid *) (payOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Extract> the <payment> from the <request: body>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Extract the <payment> from the <request: body>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: placed_to_paid> on <order: status>. + Accept the <transition: placed_to_paid> on <order: status>. - <Update> the <order: paymentMethod> from the <payment: paymentMethod>. - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Update the <order: paymentMethod> from the <payment: paymentMethod>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } (* Ship an order - transitions from paid to shipped *) (shipOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Extract> the <shipping> from the <request: body>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Extract the <shipping> from the <request: body>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: paid_to_shipped> on <order: status>. + Accept the <transition: paid_to_shipped> on <order: status>. - <Update> the <order: trackingNumber> + Update the <order: trackingNumber> from the <shipping: trackingNumber>. - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } (* Deliver an order - transitions from shipped to delivered *) (deliverOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: shipped_to_delivered> on <order: status>. + Accept the <transition: shipped_to_delivered> on <order: status>. - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } ``` @@ -336,14 +336,14 @@ Real business processes have more than one terminal state. Orders can be cancell ```aro (* Cancel an order - only valid from draft state *) (cancelOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: draft_to_cancelled> on <order: status>. + Accept the <transition: draft_to_cancelled> on <order: status>. - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } ``` @@ -355,15 +355,15 @@ One approach is multiple feature sets with different transitions: (* Cancel from draft *) (cancelDraftOrder: Order Management) { (* ... *) - <Accept> the <transition: draft_to_cancelled> on <order: status>. + Accept the <transition: draft_to_cancelled> on <order: status>. (* ... *) } (* Cancel from placed - might require refund logic *) (cancelPlacedOrder: Order Management) { (* ... *) - <Accept> the <transition: placed_to_cancelled> on <order: status>. - <Emit> a <RefundRequired: event> with <order>. + Accept the <transition: placed_to_cancelled> on <order: status>. + Emit a <RefundRequired: event> with <order>. (* ... *) } ``` @@ -372,23 +372,23 @@ Another approach is conditional logic using standard control flow: ```aro (cancelOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. (* Check current state and apply appropriate transition *) match <order: status> { case "draft" { - <Accept> the <transition: draft_to_cancelled> on <order: status>. + Accept the <transition: draft_to_cancelled> on <order: status>. } case "placed" { - <Accept> the <transition: placed_to_cancelled> on <order: status>. - <Emit> a <RefundRequired: event> with <order>. + Accept the <transition: placed_to_cancelled> on <order: status>. + Emit a <RefundRequired: event> with <order>. } } - <Store> the <order> into the <order-repository>. - <Return> an <OK: status> with <order>. + Store the <order> into the <order-repository>. + Return an <OK: status> with <order>. } ``` @@ -420,30 +420,30 @@ State transitions naturally pair with events. When an order moves to a new state ```aro (shipOrder: Order Management) { - <Extract> the <order-id> from the <pathParameters: id>. - <Retrieve> the <order> from the <order-repository> + Extract the <order-id> from the <pathParameters: id>. + Retrieve the <order> from the <order-repository> where <id> is <order-id>. - <Accept> the <transition: paid_to_shipped> on <order: status>. + Accept the <transition: paid_to_shipped> on <order: status>. - <Store> the <order> into the <order-repository>. + Store the <order> into the <order-repository>. (* Notify interested parties *) - <Emit> an <OrderShipped: event> with <order>. + Emit an <OrderShipped: event> with <order>. - <Return> an <OK: status> with <order>. + Return an <OK: status> with <order>. } (* Handler reacts to the state change *) (Notify Customer: OrderShipped Handler) { - <Extract> the <order> from the <event: order>. - <Extract> the <customer-email> from the <order: customerEmail>. - <Extract> the <tracking> from the <order: trackingNumber>. + Extract the <order> from the <event: order>. + Extract the <customer-email> from the <order: customerEmail>. + Extract the <tracking> from the <order: trackingNumber>. - <Send> the <shipping-notification: email> to <customer-email> + Send the <shipping-notification: email> to <customer-email> with <tracking>. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } ``` @@ -458,10 +458,10 @@ Sometimes you want handlers to only execute when an entity is in a specific stat ```aro (* Only process orders that are in "paid" state *) (Process Paid Order: OrderUpdated Handler<status:paid>) { - <Extract> the <order> from the <event: order>. + Extract the <order> from the <event: order>. (* This handler only runs when order.status = "paid" *) - <Process> the <fulfillment> for the <order>. - <Return> an <OK: status> for the <processing>. + Process the <fulfillment> for the <order>. + Return an <OK: status> for the <processing>. } ``` @@ -474,16 +474,16 @@ State guards use angle bracket syntax after "Handler": ```aro (* Handle orders that are paid OR shipped *) (Track Fulfillment: OrderUpdated Handler<status:paid,shipped>) { - <Extract> the <order> from the <event: order>. - <Log> "Tracking update" to the <console>. - <Return> an <OK: status> for the <tracking>. + Extract the <order> from the <event: order>. + Log "Tracking update" to the <console>. + Return an <OK: status> for the <tracking>. } (* Only premium customers with delivered orders *) (VIP Reward: OrderUpdated Handler<status:delivered;tier:premium>) { - <Extract> the <order> from the <event: order>. - <Send> the <reward> to the <order: email>. - <Return> an <OK: status> for the <reward>. + Extract the <order> from the <event: order>. + Send the <reward> to the <order: email>. + Return an <OK: status> for the <reward>. } ``` diff --git a/Book/TheLanguageGuide/Chapter27-Modules.md b/Book/TheLanguageGuide/Chapter27-Modules.md index 0d1fffa9..cffedcb4 100644 --- a/Book/TheLanguageGuide/Chapter27-Modules.md +++ b/Book/TheLanguageGuide/Chapter27-Modules.md @@ -88,15 +88,15 @@ Module A provides a single endpoint at `/module-a`: (* Module A - Standalone Application *) (Application-Start: ModuleA) { - <Log> "Module A starting..." to the <console>. - <Start> the <http-server> for the <contract>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "Module A starting..." to the <console>. + Start the <http-server> for the <contract>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } (getModuleA: ModuleA API) { - <Create> the <response> with { message: "Hello from Module A" }. - <Return> an <OK: status> with <response>. + Create the <response> with { message: "Hello from Module A" }. + Return an <OK: status> with <response>. } ``` *Source: [Examples/ModulesExample/ModuleA/main.aro](../Examples/ModulesExample/ModuleA/main.aro)* @@ -116,15 +116,15 @@ Module B provides a single endpoint at `/module-b`: (* Module B - Standalone Application *) (Application-Start: ModuleB) { - <Log> "Module B starting..." to the <console>. - <Start> the <http-server> for the <contract>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "Module B starting..." to the <console>. + Start the <http-server> for the <contract>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } (getModuleB: ModuleB API) { - <Create> the <response> with { message: "Hello from Module B" }. - <Return> an <OK: status> with <response>. + Create the <response> with { message: "Hello from Module B" }. + Return an <OK: status> with <response>. } ``` *Source: [Examples/ModulesExample/ModuleB/main.aro](../Examples/ModulesExample/ModuleB/main.aro)* @@ -140,10 +140,10 @@ import ../ModuleA import ../ModuleB (Application-Start: Combined) { - <Log> "Combined application starting..." to the <console>. - <Start> the <http-server> for the <contract>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "Combined application starting..." to the <console>. + Start the <http-server> for the <contract>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } ``` *Source: [Examples/ModulesExample/Combined/main.aro](../Examples/ModulesExample/Combined/main.aro)* @@ -211,10 +211,10 @@ When you import an application, you get access to its published variables within ```aro (* In auth-service/auth.aro *) (Authenticate User: Security) { - <Extract> the <credentials> from the <request: body>. - <Retrieve> the <user> from the <user-repository> where credentials = <credentials>. - <Publish> as <authenticated-user> <user>. - <Return> an <OK: status> with <user>. + Extract the <credentials> from the <request: body>. + Retrieve the <user> from the <user-repository> where credentials = <credentials>. + Publish as <authenticated-user> <user>. + Return an <OK: status> with <user>. } ``` @@ -227,7 +227,7 @@ import ../auth-service (Process Request: Gateway) { (* Access published variable from imported application *) <Use> the <authenticated-user> in the <authorization-check>. - <Return> an <OK: status> for the <request>. + Return an <OK: status> for the <request>. } ``` diff --git a/Book/TheLanguageGuide/Chapter28-ControlFlow.md b/Book/TheLanguageGuide/Chapter28-ControlFlow.md index ae70f202..34720501 100644 --- a/Book/TheLanguageGuide/Chapter28-ControlFlow.md +++ b/Book/TheLanguageGuide/Chapter28-ControlFlow.md @@ -9,20 +9,20 @@ The `when` clause conditionally executes a single statement. If the condition is ### Syntax ```aro -<Action> the <result> preposition the <object> when <condition>. +Action the <result> preposition the <object> when <condition>. ``` ### Basic Guards ```aro (getUser: User API) { - <Extract> the <user-id> from the <pathParameters: id>. - <Retrieve> the <user> from the <user-repository> where id = <user-id>. + Extract the <user-id> from the <pathParameters: id>. + Retrieve the <user> from the <user-repository> where id = <user-id>. (* Return NotFound only when user is empty *) - <Return> a <NotFound: status> for the <missing: user> when <user> is empty. + Return a <NotFound: status> for the <missing: user> when <user> is empty. - <Return> an <OK: status> with <user>. + Return an <OK: status> with <user>. } ``` @@ -30,16 +30,16 @@ The `when` clause conditionally executes a single statement. If the condition is ```aro (* Only return OK when count is not zero *) -<Return> an <OK: status> with <items> when <count> is not 0. +Return an <OK: status> with <items> when <count> is not 0. (* Send notification only when user has email *) -<Send> the <notification> to the <user: email> when <user: email> exists. +Send the <notification> to the <user: email> when <user: email> exists. (* Log admin access only for admins *) -<Log> "admin access" to the <audit> when <user: role> = "admin". +Log "admin access" to the <audit> when <user: role> = "admin". (* Return error when validation fails *) -<Return> a <BadRequest: status> for the <invalid: input> when <validation> is failed. +Return a <BadRequest: status> for the <invalid: input> when <validation> is failed. ``` ### Comparison Operators @@ -66,16 +66,16 @@ Combine conditions with `and`, `or`, `not`: ```aro (* Multiple conditions with and *) -<Return> an <OK: status> with <user> when <user: active> is true and <user: verified> is true. +Return an <OK: status> with <user> when <user: active> is true and <user: verified> is true. (* Either condition with or *) -<Return> a <BadRequest: status> for the <unavailable: product> when <stock> is empty or <stock> < <required>. +Return a <BadRequest: status> for the <unavailable: product> when <stock> is empty or <stock> < <required>. (* Negation *) <Allow> the <access> for the <user> when not <user: banned>. (* Complex condition *) -<Grant> the <admin-features> for the <user> when (<user: role> is "admin" or <user: is-owner> is true) and <resource: public> is false. +Grant the <admin-features> for the <user> when (<user: role> is "admin" or <user: is-owner> is true) and <resource: public> is false. ``` ## Match Expressions @@ -100,33 +100,33 @@ match <value> { ```aro (PUT /orders/{id}/status: Order API) { - <Extract> the <order-id> from the <pathParameters: id>. - <Extract> the <new-status> from the <request: body.status>. - <Retrieve> the <order> from the <order-repository> where id = <order-id>. + Extract the <order-id> from the <pathParameters: id>. + Extract the <new-status> from the <request: body.status>. + Retrieve the <order> from the <order-repository> where id = <order-id>. match <new-status> { case "confirmed" { - <Validate> the <order> for the <confirmation-rules>. - <Emit> an <OrderConfirmed: event> with <order>. + Validate the <order> for the <confirmation-rules>. + Emit an <OrderConfirmed: event> with <order>. } case "shipped" { - <Validate> the <order> for the <shipping-rules>. - <Emit> an <OrderShipped: event> with <order>. + Validate the <order> for the <shipping-rules>. + Emit an <OrderShipped: event> with <order>. } case "delivered" { - <Emit> an <OrderDelivered: event> with <order>. + Emit an <OrderDelivered: event> with <order>. } case "cancelled" { - <Emit> an <OrderCancelled: event> with <order>. + Emit an <OrderCancelled: event> with <order>. } otherwise { - <Return> a <BadRequest: status> for the <invalid: status>. + Return a <BadRequest: status> for the <invalid: status>. } } - <Transform> the <updated-order> from the <order> with { status: <new-status> }. - <Store> the <updated-order> into the <order-repository>. - <Return> an <OK: status> with <updated-order>. + Transform the <updated-order> from the <order> with { status: <new-status> }. + Store the <updated-order> into the <order-repository>. + Return an <OK: status> with <updated-order>. } ``` @@ -135,19 +135,19 @@ match <value> { ```aro match <http: method> { case "GET" { - <Retrieve> the <resource> from the <database>. + Retrieve the <resource> from the <database>. } case "POST" { - <Create> the <resource> in the <database>. + Create the <resource> in the <database>. } case "PUT" { - <Update> the <resource> in the <database>. + Update the <resource> in the <database>. } case "DELETE" { - <Remove> the <resource> from the <database>. + Remove the <resource> from the <database>. } otherwise { - <Return> a <MethodNotAllowed: error> for the <request>. + Return a <MethodNotAllowed: error> for the <request>. } } ``` @@ -157,18 +157,18 @@ match <http: method> { ```aro match <user: subscription> { case <premium> where <user: credits> > 0 { - <Grant> the <premium-features> for the <user>. - <Deduct> the <credit> from the <user: account>. + Grant the <premium-features> for the <user>. + Deduct the <credit> from the <user: account>. } case <premium> { - <Notify> the <user> about the <low-credits>. - <Grant> the <basic-features> for the <user>. + Notify the <user> about the <low-credits>. + Grant the <basic-features> for the <user>. } case <basic> { - <Grant> the <basic-features> for the <user>. + Grant the <basic-features> for the <user>. } otherwise { - <Redirect> the <user> to the <subscription-page>. + Redirect the <user> to the <subscription-page>. } } ``` @@ -178,18 +178,18 @@ match <user: subscription> { ```aro match <status-code> { case 200 { - <Parse> the <response: body> from the <http-response>. - <Return> the <data> for the <request>. + Parse the <response: body> from the <http-response>. + Return the <data> for the <request>. } case 404 { - <Return> a <NotFound: error> for the <request>. + Return a <NotFound: error> for the <request>. } case 500 { - <Log> "server error" to the <monitoring>. - <Return> a <ServerError> for the <request>. + Log "server error" to the <monitoring>. + Return a <ServerError> for the <request>. } otherwise { - <Return> an <UnknownError> for the <request>. + Return an <UnknownError> for the <request>. } } ``` @@ -201,18 +201,18 @@ Match statements support regex patterns for flexible string matching (see **Sect ```aro match <message.text> { case /^ERROR:/i { - <Log> <message.text> to the <console>. - <Emit> an <AlertTriggered: event> with <message>. + Log <message.text> to the <console>. + Emit an <AlertTriggered: event> with <message>. } case /^WARN:/i { - <Log> <message.text> to the <console>. + Log <message.text> to the <console>. } case /^[A-Z]{3}-\d{4}$/ { (* Matches ticket IDs like "ABC-1234" *) - <Process> the <ticket-reference> from the <message>. + Process the <ticket-reference> from the <message>. } otherwise { - <Log> <message.text> to the <console>. + Log <message.text> to the <console>. } } ``` @@ -253,28 +253,28 @@ Match statements are the primary place to use regex for branching logic: ```aro (Process Message: Chat Handler) { - <Extract> the <text> from the <event: text>. + Extract the <text> from the <event: text>. match <text> { case /^\/help/i { - <Send> "Available commands: /help, /status, /quit" to the <user>. + Send "Available commands: /help, /status, /quit" to the <user>. } case /^\/status\s+(\w+)$/i { - <Emit> a <StatusQuery: event> with <text>. + Emit a <StatusQuery: event> with <text>. } case /^\/quit/i { - <Emit> a <UserDisconnected: event> with <user>. + Emit a <UserDisconnected: event> with <user>. } case /https?:\/\/[\w.-]+/i { (* Contains a URL *) <Scan> the <link> for the <security-check>. } otherwise { - <Store> the <text> into the <message-repository>. + Store the <text> into the <message-repository>. } } - <Return> an <OK: status>. + Return an <OK: status>. } ``` @@ -284,15 +284,15 @@ Filter collections based on regex pattern matching with the `matches` operator: ```aro (Filter Log Files: File Handler) { - <Retrieve> the <files> from the <file-repository>. + Retrieve the <files> from the <file-repository>. (* Filter for error log files *) - <Filter> the <error-logs> from the <files> where name matches /error-\d{4}-\d{2}-\d{2}\.log$/i. + Filter the <error-logs> from the <files> where name matches /error-\d{4}-\d{2}-\d{2}\.log$/i. (* Filter for IP addresses in text *) - <Filter> the <ip-entries> from the <log-lines> where text matches /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/. + Filter the <ip-entries> from the <log-lines> where text matches /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/. - <Return> an <OK: status> with <error-logs>. + Return an <OK: status> with <error-logs>. } ``` @@ -303,12 +303,12 @@ Repository queries support regex matching: ```aro (Search Users: User API) { (* Find users with email addresses from specific domains *) - <Retrieve> the <users> from the <user-repository> where email matches /@(company|example)\.com$/i. + Retrieve the <users> from the <user-repository> where email matches /@(company|example)\.com$/i. (* Find tickets by pattern *) - <Retrieve> the <tickets> from the <ticket-repository> where code matches /^PROJ-\d{4}$/. + Retrieve the <tickets> from the <ticket-repository> where code matches /^PROJ-\d{4}$/. - <Return> an <OK: status> with <users>. + Return an <OK: status> with <users>. } ``` @@ -318,15 +318,15 @@ Split strings using regex patterns: ```aro (Parse CSV Line: Data Handler) { - <Extract> the <line> from the <input>. + Extract the <line> from the <input>. (* Split by comma, optional whitespace *) - <Split> the <fields> from the <line> with /\s*,\s*/. + Split the <fields> from the <line> with /\s*,\s*/. (* Split by multiple delimiters *) - <Split> the <words> from the <text> with /[\s,;]+/. + Split the <words> from the <text> with /[\s,;]+/. - <Return> an <OK: status> with <fields>. + Return an <OK: status> with <fields>. } ``` @@ -334,10 +334,10 @@ The Split action supports regex flags: ```aro (* Case-insensitive split *) -<Split> the <parts> from the <text> with /AND|OR/i. +Split the <parts> from the <text> with /AND|OR/i. (* Multiline split *) -<Split> the <paragraphs> from the <document> with /\n\n+/m. +Split the <paragraphs> from the <document> with /\n\n+/m. ``` ### Common Regex Patterns @@ -347,10 +347,10 @@ The Split action supports regex flags: ```aro match <email> { case /^[\w.+-]+@[\w.-]+\.[a-zA-Z]{2,}$/i { - <Return> an <OK: status> with { valid: true }. + Return an <OK: status> with { valid: true }. } otherwise { - <Return> a <BadRequest: status> with { error: "Invalid email format" }. + Return a <BadRequest: status> with { error: "Invalid email format" }. } } ``` @@ -360,11 +360,11 @@ match <email> { ```aro match <text> { case /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/=]*)/i { - <Extract> the <url> from the <text>. - <Validate> the <url> for the <security-check>. + Extract the <url> from the <text>. + Validate the <url> for the <security-check>. } otherwise { - <Process> the <text> as the <plain-message>. + Process the <text> as the <plain-message>. } } ``` @@ -374,14 +374,14 @@ match <text> { ```aro match <phone> { case /^\+?1?\d{9,15}$/ { - <Return> an <OK: status> with { valid: true }. + Return an <OK: status> with { valid: true }. } case /^\(\d{3}\)\s*\d{3}-\d{4}$/ { (* US format: (555) 123-4567 *) - <Return> an <OK: status> with { valid: true }. + Return an <OK: status> with { valid: true }. } otherwise { - <Return> a <BadRequest: status> with { error: "Invalid phone number" }. + Return a <BadRequest: status> with { error: "Invalid phone number" }. } } ``` @@ -392,14 +392,14 @@ match <phone> { match <date-string> { case /^\d{4}-\d{2}-\d{2}$/ { (* ISO format: 2024-12-25 *) - <Parse> the <date> from the <date-string> with "yyyy-MM-dd". + Parse the <date> from the <date-string> with "yyyy-MM-dd". } case /^\d{2}\/\d{2}\/\d{4}$/ { (* US format: 12/25/2024 *) - <Parse> the <date> from the <date-string> with "MM/dd/yyyy". + Parse the <date> from the <date-string> with "MM/dd/yyyy". } otherwise { - <Return> a <BadRequest: status> with { error: "Unsupported date format" }. + Return a <BadRequest: status> with { error: "Unsupported date format" }. } } ``` @@ -410,18 +410,18 @@ match <date-string> { match <input> { case /^\/set\s+(\w+)\s+(.+)$/i { (* Matches: /set key value *) - <Extract> the <key> from the <input>. - <Extract> the <value> from the <input>. - <Store> the <value> into the <settings: key>. + Extract the <key> from the <input>. + Extract the <value> from the <input>. + Store the <value> into the <settings: key>. } case /^\/get\s+(\w+)$/i { (* Matches: /get key *) - <Extract> the <key> from the <input>. - <Retrieve> the <value> from the <settings: key>. - <Return> an <OK: status> with <value>. + Extract the <key> from the <input>. + Retrieve the <value> from the <settings: key>. + Return an <OK: status> with <value>. } otherwise { - <Return> a <BadRequest: status> with { error: "Unknown command" }. + Return a <BadRequest: status> with { error: "Unknown command" }. } } ``` @@ -429,9 +429,9 @@ match <input> { #### Log Level Filtering ```aro -<Filter> the <error-logs> from the <logs> where message matches /^\[ERROR\]/i. -<Filter> the <warning-logs> from the <logs> where message matches /^\[WARN(ING)?\]/i. -<Filter> the <critical-logs> from the <logs> where message matches /^\[(ERROR|FATAL|CRITICAL)\]/i. +Filter the <error-logs> from the <logs> where message matches /^\[ERROR\]/i. +Filter the <warning-logs> from the <logs> where message matches /^\[WARN(ING)?\]/i. +Filter the <critical-logs> from the <logs> where message matches /^\[(ERROR|FATAL|CRITICAL)\]/i. ``` ### Best Practices @@ -480,7 +480,7 @@ match <phone> { (* Good - clear intent *) match <email> { case /^[\w.+-]+@[\w.-]+\.[a-zA-Z]{2,}$/i { - <Validate> the <email>. + Validate the <email>. } } @@ -523,14 +523,14 @@ ARO's syntax prioritizes readability and inline usage within statements. ```aro (POST /users: User API) { - <Extract> the <user-data> from the <request: body>. - <Validate> the <user-data> for the <user-schema>. + Extract the <user-data> from the <request: body>. + Validate the <user-data> for the <user-schema>. - <Return> a <BadRequest: status> with <validation: errors> when <validation> is failed. + Return a <BadRequest: status> with <validation: errors> when <validation> is failed. - <Create> the <user> with <user-data>. - <Store> the <user> into the <user-repository>. - <Return> a <Created: status> with <user>. + Create the <user> with <user-data>. + Store the <user> into the <user-repository>. + Return a <Created: status> with <user>. } ``` @@ -538,12 +538,12 @@ ARO's syntax prioritizes readability and inline usage within statements. ```aro (GET /products/{id}: Product API) { - <Extract> the <product-id> from the <pathParameters: id>. - <Retrieve> the <product> from the <product-repository> where id = <product-id>. + Extract the <product-id> from the <pathParameters: id>. + Retrieve the <product> from the <product-repository> where id = <product-id>. - <Return> a <NotFound: status> for the <missing: product> when <product> is empty. + Return a <NotFound: status> for the <missing: product> when <product> is empty. - <Return> an <OK: status> with <product>. + Return an <OK: status> with <product>. } ``` @@ -551,16 +551,16 @@ ARO's syntax prioritizes readability and inline usage within statements. ```aro (DELETE /posts/{id}: Post API) { - <Extract> the <post-id> from the <pathParameters: id>. - <Retrieve> the <post> from the <post-repository> where id = <post-id>. + Extract the <post-id> from the <pathParameters: id>. + Retrieve the <post> from the <post-repository> where id = <post-id>. - <Return> a <NotFound: status> for the <missing: post> when <post> is empty. + Return a <NotFound: status> for the <missing: post> when <post> is empty. - <Return> a <Forbidden: status> for the <unauthorized: deletion> + Return a <Forbidden: status> for the <unauthorized: deletion> when <post: authorId> is not <current-user: id> and <current-user: role> is not "admin". - <Delete> the <post> from the <post-repository> where id = <post-id>. - <Return> a <NoContent: status> for the <deletion>. + Delete the <post> from the <post-repository> where id = <post-id>. + Return a <NoContent: status> for the <deletion>. } ``` @@ -570,23 +570,23 @@ Check error conditions early with guarded returns: ```aro (POST /transfer: Banking) { - <Extract> the <amount> from the <request: body.amount>. - <Extract> the <from-account> from the <request: body.from>. - <Extract> the <to-account> from the <request: body.to>. + Extract the <amount> from the <request: body.amount>. + Extract the <from-account> from the <request: body.from>. + Extract the <to-account> from the <request: body.to>. (* Early exits for invalid input *) - <Return> a <BadRequest: status> for the <invalid: amount> when <amount> <= 0. - <Return> a <BadRequest: status> for the <same: accounts> when <from-account> is <to-account>. + Return a <BadRequest: status> for the <invalid: amount> when <amount> <= 0. + Return a <BadRequest: status> for the <same: accounts> when <from-account> is <to-account>. - <Retrieve> the <source> from the <account-repository> where id = <from-account>. + Retrieve the <source> from the <account-repository> where id = <from-account>. - <Return> a <NotFound: status> for the <missing: source-account> when <source> is empty. - <Return> a <BadRequest: status> for the <insufficient: funds> when <source: balance> < <amount>. + Return a <NotFound: status> for the <missing: source-account> when <source> is empty. + Return a <BadRequest: status> for the <insufficient: funds> when <source: balance> < <amount>. (* Now proceed with transfer *) - <Retrieve> the <destination> from the <account-repository> where id = <to-account>. + Retrieve the <destination> from the <account-repository> where id = <to-account>. <Transfer> the <amount> from the <source> to the <destination>. - <Return> an <OK: status> for the <transfer>. + Return an <OK: status> for the <transfer>. } ``` @@ -594,19 +594,19 @@ Check error conditions early with guarded returns: ```aro (POST /orders: Order API) { - <Extract> the <order-data> from the <request: body>. - <Create> the <order> with <order-data>. + Extract the <order-data> from the <request: body>. + Create the <order> with <order-data>. (* Conditional discount *) - <Compute> the <discount> with <order: total> * 0.1 when <order: total> >= 100. - <Transform> the <order> from the <order> with { discount: <discount> } when <discount> exists. + Compute the <discount> with <order: total> * 0.1 when <order: total> >= 100. + Transform the <order> from the <order> with { discount: <discount> } when <discount> exists. (* Conditional express shipping *) - <Compute> the <express-fee> for the <order> when <order: express> is true. - <Transform> the <order> from the <order> with { shippingFee: <express-fee> } when <express-fee> exists. + Compute the <express-fee> for the <order> when <order: express> is true. + Transform the <order> from the <order> with { shippingFee: <express-fee> } when <express-fee> exists. - <Store> the <order> into the <order-repository>. - <Return> a <Created: status> with <order>. + Store the <order> into the <order-repository>. + Return a <Created: status> with <order>. } ``` @@ -614,53 +614,53 @@ Check error conditions early with guarded returns: ```aro (User Authentication: Security) { - <Require> the <request> from the <framework>. - <Require> the <user-repository> from the <framework>. + Require the <request> from the <framework>. + Require the <user-repository> from the <framework>. (* Extract credentials *) - <Extract> the <username> from the <request: body>. - <Extract> the <password> from the <request: body>. + Extract the <username> from the <request: body>. + Extract the <password> from the <request: body>. (* Validate input - guarded return *) - <Return> a <BadRequest: error> for the <request> + Return a <BadRequest: error> for the <request> when <username> is empty or <password> is empty. (* Look up user *) - <Retrieve> the <user> from the <user-repository>. + Retrieve the <user> from the <user-repository>. (* Handle user not found - guarded statements *) - <Log> <username> to the <console> when <user> is null. - <Return> an <Unauthorized: error> for the <request> when <user> is null. + Log <username> to the <console> when <user> is null. + Return an <Unauthorized: error> for the <request> when <user> is null. (* Check account status with match *) match <user: status> { case "locked" { - <Return> an <AccountLocked: error> for the <request>. + Return an <AccountLocked: error> for the <request>. } case "pending" { - <Send> the <verification-email> to the <user: email>. - <Return> a <PendingVerification: status> for the <request>. + Send the <verification-email> to the <user: email>. + Return a <PendingVerification: status> for the <request>. } case "active" { (* Verify password *) - <Compute> the <password-hash> for the <password>. + Compute the <password-hash> for the <password>. match <password-hash> { case <user: password-hash> { - <Create> the <session-token> for the <user>. - <Log> <user> to the <console>. - <Return> an <OK: status> with the <session-token>. + Create the <session-token> for the <user>. + Log <user> to the <console>. + Return an <OK: status> with the <session-token>. } otherwise { - <Increment> the <failed-attempts> for the <user>. - <Lock> the <user: account> for the <security-policy> + Increment the <failed-attempts> for the <user>. + Lock the <user: account> for the <security-policy> when <failed-attempts> >= 5. - <Return> an <Unauthorized: error> for the <request>. + Return an <Unauthorized: error> for the <request>. } } } otherwise { - <Return> an <InvalidAccountStatus: error> for the <request>. + Return an <InvalidAccountStatus: error> for the <request>. } } } @@ -677,12 +677,12 @@ Guards with `when` are ideal for: ```aro (* Good - guards for early exit *) -<Return> a <BadRequest: status> for the <missing: id> when <user-id> is empty. -<Return> a <NotFound: status> for the <missing: user> when <user> is empty. -<Return> a <Forbidden: status> for the <private: profile> when <user: private> is true. +Return a <BadRequest: status> for the <missing: id> when <user-id> is empty. +Return a <NotFound: status> for the <missing: user> when <user> is empty. +Return a <Forbidden: status> for the <private: profile> when <user: private> is true. (* Continue with main logic *) -<Return> an <OK: status> with <user>. +Return an <OK: status> with <user>. ``` ### Use Match for Multiple Outcomes @@ -708,10 +708,10 @@ match <order: status> { ```aro (* Good - explicit conditions *) -<Grant> the <access> for the <user> when <user: active> is true and <user: verified> is true. +Grant the <access> for the <user> when <user: active> is true and <user: verified> is true. (* Avoid - implicit truthiness *) -<Grant> the <access> for the <user> when <user: active> and <user: verified>. +Grant the <access> for the <user> when <user: active> and <user: verified>. ``` --- diff --git a/Book/TheLanguageGuide/Chapter29-DataPipelines.md b/Book/TheLanguageGuide/Chapter29-DataPipelines.md index f8299c60..79a0cb34 100644 --- a/Book/TheLanguageGuide/Chapter29-DataPipelines.md +++ b/Book/TheLanguageGuide/Chapter29-DataPipelines.md @@ -8,10 +8,10 @@ ARO supports four core data operations: | Operation | Purpose | Example | |-----------|---------|---------| -| **Retrieve** | Retrieve and filter data | `<Retrieve> the <users: List<User>> from the <repository>...` | -| **Filter** | Filter existing collection | `<Filter> the <active: List<User>> from the <users>...` | -| **Map** | Transform to different type | `<Map> the <summaries> as List<UserSummary> from the <users>.` | -| **Reduce** | Aggregate to single value | `<Reduce> the <total> as Float from the <orders> with sum(<amount>).` | +| **Retrieve** | Retrieve and filter data | `Retrieve the <users: List<User>> from the <repository>...` | +| **Filter** | Filter existing collection | `Filter the <active: List<User>> from the <users>...` | +| **Map** | Transform to different type | `Map the <summaries> as List<UserSummary> from the <users>.` | +| **Reduce** | Aggregate to single value | `Reduce the <total> as Float from the <orders> with sum(<amount>).` | ### Type Annotation Syntax @@ -19,10 +19,10 @@ ARO supports two equivalent syntaxes for type annotations: ```aro (* Colon syntax: type inside angle brackets *) -<Filter> the <active-users: List<User>> from the <users> where <active> is true. +Filter the <active-users: List<User>> from the <users> where <active> is true. (* As syntax: type follows the result descriptor *) -<Filter> the <active-users> as List<User> from the <users> where <active> is true. +Filter the <active-users> as List<User> from the <users> where <active> is true. ``` Both produce identical results. The `as Type` syntax (ARO-0038) can be more readable when the variable name is long, while the colon syntax keeps everything compact. Type annotations are optional since ARO infers types from the source collection. @@ -35,24 +35,24 @@ Retrieves data with optional filtering, sorting, and pagination. ```aro (* Basic retrieve *) -<Retrieve> the <users: List<User>> from the <user-repository>. +Retrieve the <users: List<User>> from the <user-repository>. (* With filter *) -<Retrieve> the <active-users: List<User>> from the <users> +Retrieve the <active-users: List<User>> from the <users> where <status> is "active". (* With sorting *) -<Retrieve> the <recent-users: List<User>> from the <users> +Retrieve the <recent-users: List<User>> from the <users> order by <created-at> desc. (* With pagination *) -<Retrieve> the <page: List<User>> from the <users> +Retrieve the <page: List<User>> from the <users> order by <name> asc limit 20 offset 40. (* Combined *) -<Retrieve> the <top-customers: List<User>> from the <users> +Retrieve the <top-customers: List<User>> from the <users> where <tier> is "premium" order by <total-purchases> desc limit 10. @@ -66,15 +66,15 @@ Filters an existing collection with a predicate. ```aro (* Filter by equality *) -<Filter> the <admins: List<User>> from the <users> +Filter the <admins: List<User>> from the <users> where <role> is "admin". (* Filter by comparison *) -<Filter> the <high-value: List<Order>> from the <orders> +Filter the <high-value: List<Order>> from the <orders> where <amount> > 1000. (* Filter with multiple conditions *) -<Filter> the <active-premium: List<User>> from the <users> +Filter the <active-premium: List<User>> from the <users> where <status> is "active" and <tier> is "premium". ``` @@ -99,16 +99,16 @@ The `in` and `not in` operators test set membership. They accept either a CSV st ```aro (* Using CSV string *) -<Filter> the <pending: List<Order>> from the <orders> +Filter the <pending: List<Order>> from the <orders> where <status> in "pending,processing". (* Using array variable *) -<Create> the <exclude-statuses> with ["cancelled", "refunded"]. -<Filter> the <active: List<Order>> from the <orders> +Create the <exclude-statuses> with ["cancelled", "refunded"]. +Filter the <active: List<Order>> from the <orders> where <status> not in <exclude-statuses>. (* Combining with other conditions *) -<Filter> the <valid-orders: List<Order>> from the <orders> +Filter the <valid-orders: List<Order>> from the <orders> where <amount> > 0 and <status> not in <exclude-statuses>. ``` @@ -116,11 +116,11 @@ The `matches` operator supports regex literals with flags: ```aro (* Filter users with admin emails *) -<Filter> the <admins: List<User>> from the <users> +Filter the <admins: List<User>> from the <users> where <email> matches /^admin@|@admin\./i. (* Filter valid email addresses *) -<Filter> the <valid-emails: List<User>> from the <users> +Filter the <valid-emails: List<User>> from the <users> where <email> matches /^[\w.+-]+@[\w.-]+\.[a-zA-Z]{2,}$/i. ``` @@ -132,7 +132,7 @@ Transforms a collection to a different OpenAPI-defined type. The runtime automat ```aro (* Map User to UserSummary *) -<Map> the <summaries: List<UserSummary>> from the <users>. +Map the <summaries: List<UserSummary>> from the <users>. ``` **Requirements:** @@ -174,23 +174,23 @@ Aggregates a collection to a single value using aggregation functions. ```aro (* Count items *) -<Reduce> the <user-count: Integer> from the <users> +Reduce the <user-count: Integer> from the <users> with count(). (* Sum numeric field *) -<Reduce> the <total-revenue: Float> from the <orders> +Reduce the <total-revenue: Float> from the <orders> with sum(<amount>). (* Average *) -<Reduce> the <avg-price: Float> from the <products> +Reduce the <avg-price: Float> from the <products> with avg(<price>). (* Min/Max *) -<Reduce> the <highest-score: Float> from the <scores> +Reduce the <highest-score: Float> from the <scores> with max(<value>). (* With filter *) -<Reduce> the <pending-count: Integer> from the <orders> +Reduce the <pending-count: Integer> from the <orders> where <status> is "pending" with count(). ``` @@ -216,22 +216,22 @@ Chain operations to build complex data transformations: ```aro (Generate Report: Analytics) { (* Step 1: Retrieve recent orders *) - <Retrieve> the <recent-orders: List<Order>> from the <orders> + Retrieve the <recent-orders: List<Order>> from the <orders> where <created-at> > now().minus(30.days) order by <created-at> desc. (* Step 2: Filter high-value orders *) - <Filter> the <high-value: List<Order>> from the <recent-orders> + Filter the <high-value: List<Order>> from the <recent-orders> where <amount> > 1000. (* Step 3: Map to summaries *) - <Map> the <summaries: List<OrderSummary>> from the <high-value>. + Map the <summaries: List<OrderSummary>> from the <high-value>. (* Step 4: Calculate total *) - <Reduce> the <total: Float> from the <high-value> + Reduce the <total: Float> from the <high-value> with sum(<amount>). - <Return> an <OK: status> with { + Return an <OK: status> with { orders: <summaries>, total: <total>, count: <high-value>.count() @@ -247,15 +247,15 @@ Sort results by one or more fields: ```aro (* Single field, ascending *) -<Retrieve> the <users: List<User>> from the <repository> +Retrieve the <users: List<User>> from the <repository> order by <name> asc. (* Single field, descending *) -<Retrieve> the <recent: List<Order>> from the <orders> +Retrieve the <recent: List<Order>> from the <orders> order by <created-at> desc. (* Multiple fields *) -<Retrieve> the <products: List<Product>> from the <catalog> +Retrieve the <products: List<Product>> from the <catalog> order by <category> asc, <price> desc. ``` @@ -267,18 +267,18 @@ Limit results with offset for pagination: ```aro (* First page: items 1-20 *) -<Retrieve> the <page1: List<User>> from the <users> +Retrieve the <page1: List<User>> from the <users> order by <name> asc limit 20. (* Second page: items 21-40 *) -<Retrieve> the <page2: List<User>> from the <users> +Retrieve the <page2: List<User>> from the <users> order by <name> asc limit 20 offset 20. (* Third page: items 41-60 *) -<Retrieve> the <page3: List<User>> from the <users> +Retrieve the <page3: List<User>> from the <users> order by <name> asc limit 20 offset 40. @@ -324,38 +324,38 @@ components: ```aro (* Application entry point *) (Application-Start: Order Analytics) { - <Log> "Order Analytics ready" to the <console>. - <Return> an <OK: status> for the <startup>. + Log "Order Analytics ready" to the <console>. + Return an <OK: status> for the <startup>. } (* Analytics report generation *) (Generate Report: Order Analytics) { (* Retrieve recent orders *) - <Retrieve> the <recent: List<Order>> from the <orders> + Retrieve the <recent: List<Order>> from the <orders> where <created-at> > now().minus(30.days) order by <created-at> desc. (* Calculate metrics *) - <Reduce> the <total-revenue: Float> from the <recent> + Reduce the <total-revenue: Float> from the <recent> with sum(<amount>). - <Reduce> the <order-count: Integer> from the <recent> + Reduce the <order-count: Integer> from the <recent> with count(). - <Reduce> the <avg-order: Float> from the <recent> + Reduce the <avg-order: Float> from the <recent> with avg(<amount>). (* Filter pending orders *) - <Filter> the <pending: List<Order>> from the <recent> + Filter the <pending: List<Order>> from the <recent> where <status> is "pending". - <Reduce> the <pending-count: Integer> from the <pending> + Reduce the <pending-count: Integer> from the <pending> with count(). (* Map to summaries for response *) - <Map> the <summaries: List<OrderSummary>> from the <recent>. + Map the <summaries: List<OrderSummary>> from the <recent>. - <Return> an <OK: status> with { + Return an <OK: status> with { orders: <summaries>, metrics: { total-revenue: <total-revenue>, @@ -389,24 +389,24 @@ When working with data pipelines, keep these performance guidelines in mind: ```aro (* Good: Filter first, then transform *) -<Filter> the <active: List<User>> from the <users> +Filter the <active: List<User>> from the <users> where <status> is "active". -<Map> the <summaries: List<UserSummary>> from the <active>. +Map the <summaries: List<UserSummary>> from the <active>. (* Less efficient: Transform all, filter none *) -<Map> the <all-summaries: List<UserSummary>> from the <users>. +Map the <all-summaries: List<UserSummary>> from the <users>. ``` 2. **Limit Results**: Use `limit` with sorting to avoid processing unnecessary data. ```aro (* Good: Retrieve only top 10 *) -<Retrieve> the <top-orders: List<Order>> from the <orders> +Retrieve the <top-orders: List<Order>> from the <orders> order by <amount> desc limit 10. (* Expensive: Retrieve all, then filter in application *) -<Retrieve> the <all-orders: List<Order>> from the <orders> +Retrieve the <all-orders: List<Order>> from the <orders> order by <amount> desc. ``` @@ -414,13 +414,13 @@ When working with data pipelines, keep these performance guidelines in mind: ```aro (* Good: Single filter with combined conditions *) -<Filter> the <premium-active: List<User>> from the <users> +Filter the <premium-active: List<User>> from the <users> where <status> is "active" and <tier> is "premium". (* Less efficient: Two separate filter passes *) -<Filter> the <active: List<User>> from the <users> +Filter the <active: List<User>> from the <users> where <status> is "active". -<Filter> the <premium-active: List<User>> from the <active> +Filter the <premium-active: List<User>> from the <active> where <tier> is "premium". ``` @@ -428,12 +428,12 @@ When working with data pipelines, keep these performance guidelines in mind: ```aro (* Good: Aggregate directly *) -<Reduce> the <user-count: Integer> from the <users> +Reduce the <user-count: Integer> from the <users> with count(). (* Expensive: Retrieve all just to count *) -<Retrieve> the <all-users: List<User>> from the <users>. -<Compute> the <count: length> from <all-users>. +Retrieve the <all-users: List<User>> from the <users>. +Compute the <count: length> from <all-users>. ``` ### Memory Considerations @@ -450,21 +450,21 @@ For very complex data transformations, consider splitting into multiple feature ```aro (* Feature set 1: Heavy data processing *) (Process Orders: Order Handler) { - <Retrieve> the <orders: List<Order>> from the <order-repository> + Retrieve the <orders: List<Order>> from the <order-repository> where <status> is "pending" limit 1000. - <Store> the <orders> into the <pending-cache>. - <Emit> a <OrdersProcessed: event> with { count: <orders>.count() }. - <Return> an <OK: status> for the <processing>. + Store the <orders> into the <pending-cache>. + Emit a <OrdersProcessed: event> with { count: <orders>.count() }. + Return an <OK: status> for the <processing>. } (* Feature set 2: Analytics on cached data *) (Generate Report: OrdersProcessed Handler) { - <Retrieve> the <orders: List<Order>> from the <pending-cache>. - <Reduce> the <total: Float> from the <orders> + Retrieve the <orders: List<Order>> from the <pending-cache>. + Reduce the <total: Float> from the <orders> with sum(<amount>). (* ... additional analytics ... *) - <Return> an <OK: status> with { total: <total> }. + Return an <OK: status> with { total: <total> }. } ``` diff --git a/Book/TheLanguageGuide/Chapter30-Repositories.md b/Book/TheLanguageGuide/Chapter30-Repositories.md index b5e8ae67..e0d5cfb8 100644 --- a/Book/TheLanguageGuide/Chapter30-Repositories.md +++ b/Book/TheLanguageGuide/Chapter30-Repositories.md @@ -9,9 +9,9 @@ In ARO, each HTTP request creates a fresh execution context. Variables defined i ```aro (* This won't work - count resets on each request *) (GET /count: Counter API) { - <Create> the <count> with 0. - <Compute> the <new-count> from <count> + 1. - <Return> an <OK: status> with <new-count>. + Create the <count> with 0. + Compute the <new-count> from <count> + 1. + Return an <OK: status> with <new-count>. } ``` @@ -19,16 +19,16 @@ Repositories solve this by providing shared storage: ```aro (POST /increment: Counter API) { - <Retrieve> the <counts> from the <counter-repository>. - <Compute> the <current> from <counts: length>. - <Store> the <current> into the <counter-repository>. - <Return> an <OK: status> with <current>. + Retrieve the <counts> from the <counter-repository>. + Compute the <current> from <counts: length>. + Store the <current> into the <counter-repository>. + Return an <OK: status> with <current>. } (GET /count: Counter API) { - <Retrieve> the <counts> from the <counter-repository>. - <Compute> the <total> from <counts: length>. - <Return> an <OK: status> with { count: <total> }. + Retrieve the <counts> from the <counter-repository>. + Compute the <total> from <counts: length>. + Return an <OK: status> with { count: <total> }. } ``` @@ -59,7 +59,7 @@ The naming convention: Use the `<Store>` action to save data to a repository: ```aro -<Store> the <data> into the <name-repository>. +Store the <data> into the <name-repository>. ``` ### Preposition Variants @@ -67,9 +67,9 @@ Use the `<Store>` action to save data to a repository: All of these are equivalent: ```aro -<Store> the <user> into the <user-repository>. -<Store> the <user> in the <user-repository>. -<Store> the <user> to the <user-repository>. +Store the <user> into the <user-repository>. +Store the <user> in the <user-repository>. +Store the <user> to the <user-repository>. ``` ### Storage Semantics @@ -78,15 +78,15 @@ Repositories use **list-based storage**. Each store operation appends to the lis ```aro (* First request *) -<Store> the <user1> into the <user-repository>. +Store the <user1> into the <user-repository>. (* Repository: [user1] *) (* Second request *) -<Store> the <user2> into the <user-repository>. +Store the <user2> into the <user-repository>. (* Repository: [user1, user2] *) (* Third request *) -<Store> the <user3> into the <user-repository>. +Store the <user3> into the <user-repository>. (* Repository: [user1, user2, user3] *) ``` @@ -99,16 +99,16 @@ When `<Store>` is called, the runtime automatically deduplicates plain values (s ```aro (Queue URL: QueueUrl Handler) { (* Just store — observer handles the rest *) - <Store> the <url> into the <crawled-repository>. - <Return> an <OK: status>. + Store the <url> into the <crawled-repository>. + Return an <OK: status>. } (Process New URLs: crawled-repository Observer) { (* Only fires for new entries, not duplicates *) - <Extract> the <url> from the <event: newValue>. - <Log> "Processing: ${<url>}" to the <console>. - <Emit> a <ProcessUrl: event> with { url: <url> }. - <Return> an <OK: status>. + Extract the <url> from the <event: newValue>. + Log "Processing: ${<url>}" to the <console>. + Emit a <ProcessUrl: event> with { url: <url> }. + Return an <OK: status>. } ``` @@ -125,8 +125,8 @@ This can be used with `when` guards, but **observers are preferred**: ```aro (* Works, but consider using an observer instead *) -<Store> the <url> into the <crawled-repository>. -<Log> "New: ${<url>}" to the <console> when <new-entry> > 0. +Store the <url> into the <crawled-repository>. +Log "New: ${<url>}" to the <console> when <new-entry> > 0. ``` Because repository operations are serialized by the runtime's Actor model, both patterns are **race-condition-free** even under `parallel for each`. @@ -135,19 +135,19 @@ Because repository operations are serialized by the runtime's Actor model, both ```aro (postMessage: Chat API) { - <Extract> the <data> from the <request: body>. - <Extract> the <text> from the <data: message>. - <Extract> the <author> from the <data: author>. + Extract the <data> from the <request: body>. + Extract the <text> from the <data: message>. + Extract the <author> from the <data: author>. - <Create> the <message> with { + Create the <message> with { text: <text>, author: <author>, timestamp: now }. - <Store> the <message> into the <message-repository>. + Store the <message> into the <message-repository>. - <Return> a <Created: status> with <message>. + Return a <Created: status> with <message>. } ``` @@ -156,7 +156,7 @@ Because repository operations are serialized by the runtime's Actor model, both Use the `<Retrieve>` action to fetch data from a repository: ```aro -<Retrieve> the <items> from the <name-repository>. +Retrieve the <items> from the <name-repository>. ``` ### Return Value @@ -169,8 +169,8 @@ Use the `<Retrieve>` action to fetch data from a repository: ```aro (getMessages: Chat API) { - <Retrieve> the <messages> from the <message-repository>. - <Return> an <OK: status> with { messages: <messages> }. + Retrieve the <messages> from the <message-repository>. + Return an <OK: status> with { messages: <messages> }. } ``` @@ -180,9 +180,9 @@ Use `where` to filter results: ```aro (getUserById: User API) { - <Extract> the <id> from the <pathParameters: id>. - <Retrieve> the <user> from the <user-repository> where id = <id>. - <Return> an <OK: status> with <user>. + Extract the <id> from the <pathParameters: id>. + Retrieve the <user> from the <user-repository> where id = <id>. + Return an <OK: status> with <user>. } ``` @@ -192,14 +192,14 @@ Use specifiers to retrieve a single item from a repository: ```aro (* Get the most recently stored item *) -<Retrieve> the <message> from the <message-repository: last>. +Retrieve the <message> from the <message-repository: last>. (* Get the first stored item *) -<Retrieve> the <message> from the <message-repository: first>. +Retrieve the <message> from the <message-repository: first>. (* Get by numeric index - 0 = most recent *) -<Retrieve> the <latest> from the <message-repository: 0>. -<Retrieve> the <second-latest> from the <message-repository: 1>. +Retrieve the <latest> from the <message-repository: 0>. +Retrieve the <second-latest> from the <message-repository: 1>. ``` Numeric indices count from most recently added (0 = newest, 1 = second newest, etc.). @@ -208,8 +208,8 @@ This is useful when you only need one item, like the latest message in a chat: ```aro (getLatestMessage: Chat API) { - <Retrieve> the <message> from the <message-repository: last>. - <Return> an <OK: status> with { message: <message> }. + Retrieve the <message> from the <message-repository: last>. + Return an <OK: status> with { message: <message> }. } ``` @@ -224,18 +224,18 @@ Repositories are scoped to their **business activity**. Feature sets with the sa (* These share the same <message-repository> *) (postMessage: Chat API) { - <Store> the <message> into the <message-repository>. - <Return> a <Created: status>. + Store the <message> into the <message-repository>. + Return a <Created: status>. } (getMessages: Chat API) { - <Retrieve> the <messages> from the <message-repository>. - <Return> an <OK: status> with <messages>. + Retrieve the <messages> from the <message-repository>. + Return an <OK: status> with <messages>. } (deleteMessage: Chat API) { (* Same repository as above *) - <Retrieve> the <messages> from the <message-repository>. + Retrieve the <messages> from the <message-repository>. (* ... *) } ``` @@ -245,13 +245,13 @@ Repositories are scoped to their **business activity**. Feature sets with the sa ```aro (* Business activity: "Chat API" *) (postMessage: Chat API) { - <Store> the <msg> into the <message-repository>. + Store the <msg> into the <message-repository>. } (* Business activity: "Admin API" - DIFFERENT repository! *) (postAuditLog: Admin API) { (* This <message-repository> is separate from Chat API's *) - <Store> the <log> into the <message-repository>. + Store the <log> into the <message-repository>. } ``` @@ -266,10 +266,10 @@ This scoping: ```aro (Application-Start: Simple Chat) { - <Log> "Starting Simple Chat..." to the <console>. - <Start> the <http-server> for the <contract>. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status> for the <startup>. + Log "Starting Simple Chat..." to the <console>. + Start the <http-server> for the <contract>. + Keepalive the <application> for the <events>. + Return an <OK: status> for the <startup>. } ``` @@ -278,17 +278,17 @@ This scoping: ```aro (* GET /status - Return the last message *) (getStatus: Simple Chat API) { - <Retrieve> the <message> from the <message-repository: last>. - <Return> an <OK: status> with { message: <message> }. + Retrieve the <message> from the <message-repository: last>. + Return an <OK: status> with { message: <message> }. } (* POST /status - Store a new message *) (postStatus: Simple Chat API) { - <Extract> the <message> from the <body: message>. + Extract the <message> from the <body: message>. - <Store> the <message> into the <message-repository>. + Store the <message> into the <message-repository>. - <Return> a <Created: status> with { message: <message> }. + Return a <Created: status> with { message: <message> }. } ``` @@ -317,16 +317,16 @@ curl http://localhost:8080/status Use the `<Delete>` action with a `where` clause to remove items from a repository: ```aro -<Delete> the <user> from the <user-repository> where id = <userId>. +Delete the <user> from the <user-repository> where id = <userId>. ``` ### Example: Deleting a User ```aro (deleteUser: User API) { - <Extract> the <userId> from the <pathParameters: id>. - <Delete> the <user> from the <user-repository> where id = <userId>. - <Return> an <OK: status> with { deleted: <userId> }. + Extract the <userId> from the <pathParameters: id>. + Delete the <user> from the <user-repository> where id = <userId>. + Return an <OK: status> with { deleted: <userId> }. } ``` @@ -342,12 +342,12 @@ Create an observer by naming your feature set's business activity as `{repositor ```aro (Audit Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Extract> the <newValue> from the <event: newValue>. - <Extract> the <oldValue> from the <event: oldValue>. + Extract the <changeType> from the <event: changeType>. + Extract the <newValue> from the <event: newValue>. + Extract the <oldValue> from the <event: oldValue>. - <Log> <changeType> to the <console>. - <Return> an <OK: status> for the <audit>. + Log <changeType> to the <console>. + Return an <OK: status> for the <audit>. } ``` @@ -376,18 +376,18 @@ Observers are triggered for three types of changes: ```aro (Track User Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Extract> the <entityId> from the <event: entityId>. + Extract the <changeType> from the <event: changeType>. + Extract the <entityId> from the <event: entityId>. - <Compare> the <changeType> equals "updated". + Compare the <changeType> equals "updated". - <Extract> the <oldName> from the <event: oldValue: name>. - <Extract> the <newName> from the <event: newValue: name>. + Extract the <oldName> from the <event: oldValue: name>. + Extract the <newName> from the <event: newValue: name>. - <Compute> the <message> from "User " + <entityId> + " renamed from " + <oldName> + " to " + <newName>. - <Log> <message> to the <console>. + Compute the <message> from "User " + <entityId> + " renamed from " + <oldName> + " to " + <newName>. + Log <message> to the <console>. - <Return> an <OK: status> for the <tracking>. + Return an <OK: status> for the <tracking>. } ``` @@ -398,17 +398,17 @@ You can have multiple observers for the same repository: ```aro (* Audit logging observer *) (Log All Changes: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Log> <changeType> to the <console>. - <Return> an <OK: status>. + Extract the <changeType> from the <event: changeType>. + Log <changeType> to the <console>. + Return an <OK: status>. } (* Email notification observer *) (Notify Admin: user-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Compare> the <changeType> equals "deleted". - <Send> the <notification> to the <admin-email>. - <Return> an <OK: status>. + Extract the <changeType> from the <event: changeType>. + Compare the <changeType> equals "deleted". + Send the <notification> to the <admin-email>. + Return an <OK: status>. } ``` @@ -419,12 +419,12 @@ Add a `when` clause to trigger observers only when a condition is met. This is u ```aro (* Only triggers when message count exceeds 100 *) (Cleanup Messages: message-repository Observer) when <message-repository: count> > 100 { - <Retrieve> the <all-messages> from the <message-repository>. - <Extract> the <keep-messages: 0-49> from the <all-messages>. - <Clear> the <all> from the <message-repository>. - <Store> the <keep-messages> into the <message-repository>. - <Log> "Cleaned up messages, kept last 50" to the <console>. - <Return> an <OK: status> for the <cleanup>. + Retrieve the <all-messages> from the <message-repository>. + Extract the <keep-messages: 0-49> from the <all-messages>. + Clear the <all> from the <message-repository>. + Store the <keep-messages> into the <message-repository>. + Log "Cleaned up messages, kept last 50" to the <console>. + Return an <OK: status> for the <cleanup>. } ``` @@ -435,9 +435,9 @@ The `when` guard is evaluated before the observer executes. If the condition is ```aro (* Trigger alert when queue grows too large *) (Queue Alert: task-repository Observer) when <task-repository: count> > 1000 { - <Log> "Warning: Task queue exceeds 1000 items" to the <console>. - <Emit> a <QueueOverflow: event>. - <Return> an <OK: status>. + Log "Warning: Task queue exceeds 1000 items" to the <console>. + Emit a <QueueOverflow: event>. + Return an <OK: status>. } ``` @@ -451,35 +451,35 @@ The straightforward implementation uses sequential processing: ```aro (Application-Start: Directory Replicator) { - <Create> the <template-path> with "../template". - <Log> "Scanning template directory..." to the <console>. + Create the <template-path> with "../template". + Log "Scanning template directory..." to the <console>. - <List> the <all-entries: recursively> from the <directory: template-path>. - <Filter> the <directories: List> from the <all-entries> where <isDirectory> is true. + List the <all-entries: recursively> from the <directory: template-path>. + Filter the <directories: List> from the <all-entries> where <isDirectory> is true. - <Compute> the <count: length> from the <directories>. - <Log> "Found ${count} directories" to the <console>. + Compute the <count: length> from the <directories>. + Log "Found ${count} directories" to the <console>. - <Log> "Creating directory structure..." to the <console>. + Log "Creating directory structure..." to the <console>. (* Process each directory sequentially *) - <Create> the <index> with 0. + Create the <index> with 0. (For Each: <entry> in <directories>) { - <Extract> the <fullpath> from the <entry: path>. + Extract the <fullpath> from the <entry: path>. (* Remove template/ prefix *) - <Split> the <pathparts> from the <fullpath> by /template\//. - <Extract> the <relpath: last> from the <pathparts>. + Split the <pathparts> from the <fullpath> by /template\//. + Extract the <relpath: last> from the <pathparts>. (* Create the directory *) - <Make> the <dir> to the <path: relpath>. - <Log> "Created: ${relpath}" to the <console>. + Make the <dir> to the <path: relpath>. + Log "Created: ${relpath}" to the <console>. - <Compute> the <index> from <index> + 1. + Compute the <index> from <index> + 1. } - <Log> "Replication complete!" to the <console>. - <Return> an <OK: status> for the <replication>. + Log "Replication complete!" to the <console>. + Return an <OK: status> for the <replication>. } ``` @@ -505,21 +505,21 @@ The reactive implementation uses repository observers: **main.aro**: ```aro (Application-Start: Directory Replicator Events) { - <Create> the <template-path> with "../template". - <Log> "Scanning template directory..." to the <console>. + Create the <template-path> with "../template". + Log "Scanning template directory..." to the <console>. - <List> the <all-entries: recursively> from the <directory: template-path>. - <Filter> the <directories: List> from the <all-entries> where <isDirectory> is true. + List the <all-entries: recursively> from the <directory: template-path>. + Filter the <directories: List> from the <all-entries> where <isDirectory> is true. - <Compute> the <count: length> from the <directories>. - <Log> "Found ${count} directories" to the <console>. + Compute the <count: length> from the <directories>. + Log "Found ${count} directories" to the <console>. - <Log> "Storing directories to repository..." to the <console>. + Log "Storing directories to repository..." to the <console>. (* Store directories - triggers observers for each item *) - <Store> the <directories> into the <directory-repository>. + Store the <directories> into the <directory-repository>. - <Return> an <OK: status> for the <replication>. + Return an <OK: status> for the <replication>. } ``` @@ -528,32 +528,32 @@ The reactive implementation uses repository observers: (* Main observer: Creates each directory when stored *) (Process Directory Entry: directory-repository Observer) { (* Extract the directory entry from the event *) - <Extract> the <entry> from the <event: newValue>. - <Extract> the <fullpath> from the <entry: path>. + Extract the <entry> from the <event: newValue>. + Extract the <fullpath> from the <entry: path>. (* Split to remove template/ prefix from absolute path *) - <Split> the <pathparts> from the <fullpath> by /template\//. + Split the <pathparts> from the <fullpath> by /template\//. (* Get the last element (relative path) *) - <Extract> the <relpath: last> from the <pathparts>. + Extract the <relpath: last> from the <pathparts>. (* Create the directory in current location *) - <Make> the <dir> to the <path: relpath>. + Make the <dir> to the <path: relpath>. (* Log the created directory *) - <Log> "Created: ${relpath}" to the <console>. + Log "Created: ${relpath}" to the <console>. - <Return> an <OK: status> for the <processing>. + Return an <OK: status> for the <processing>. } (* Audit observer: Tracks all repository changes *) (Audit Directory Changes: directory-repository Observer) { - <Extract> the <changeType> from the <event: changeType>. - <Extract> the <repositoryName> from the <event: repositoryName>. + Extract the <changeType> from the <event: changeType>. + Extract the <repositoryName> from the <event: repositoryName>. - <Log> "[AUDIT] ${repositoryName}: ${changeType}" to the <console>. + Log "[AUDIT] ${repositoryName}: ${changeType}" to the <console>. - <Return> an <OK: status> for the <audit>. + Return an <OK: status> for the <audit>. } ``` @@ -638,13 +638,13 @@ To add new functionality: (* Existing code... *) (* NEW: Calculate total size? Must add here! *) - <Compute> the <total-size>... + Compute the <total-size>... (* NEW: Send notification? Must add here! *) - <Send> the <notification>... + Send the <notification>... (* NEW: Validate permissions? Must add here! *) - <Validate> the <permissions>... + Validate the <permissions>... } ``` @@ -652,7 +652,7 @@ To add new functionality: ```aro (* NEW: Calculate total size *) (Track Size: directory-repository Observer) { - <Extract> the <entry> from the <event: newValue>. + Extract the <entry> from the <event: newValue>. (* Calculate and track size *) } @@ -663,7 +663,7 @@ To add new functionality: (* NEW: Validate permissions *) (Check Permissions: directory-repository Observer) { - <Extract> the <entry> from the <event: newValue>. + Extract the <entry> from the <event: newValue>. (* Validate permissions *) } ``` @@ -729,7 +729,7 @@ aro run main.aro A critical feature: when you store an **array** to a repository, ARO emits **per-item events**: ```aro -<Store> the <directories> into the <directory-repository>. +Store the <directories> into the <directory-repository>. (* If directories = [dir1, dir2, dir3] *) (* Emits 3 separate events: *) (* - event { newValue: dir1, changeType: "created" } *) @@ -818,15 +818,15 @@ Store simple, serializable data: ```aro (* Good - simple object *) -<Create> the <user> with { +Create the <user> with { id: <id>, name: <name>, email: <email> }. -<Store> the <user> into the <user-repository>. +Store the <user> into the <user-repository>. (* Avoid - complex nested structures *) -<Store> the <entire-request-context> into the <debug-repository>. +Store the <entire-request-context> into the <debug-repository>. ``` --- diff --git a/Book/TheLanguageGuide/Chapter31-SystemCommands.md b/Book/TheLanguageGuide/Chapter31-SystemCommands.md index d7b08e46..f36b7f93 100644 --- a/Book/TheLanguageGuide/Chapter31-SystemCommands.md +++ b/Book/TheLanguageGuide/Chapter31-SystemCommands.md @@ -10,13 +10,13 @@ The preferred syntax places the command name in the object specifier: ```aro (* Simple command *) -<Exec> the <result> for the <command: "uptime">. +Exec the <result> for the <command: "uptime">. (* Command with arguments *) -<Exec> the <result> for the <command: "ls"> with "-la". +Exec the <result> for the <command: "ls"> with "-la". (* Command with multiple arguments *) -<Exec> the <result> for the <command: "ls"> with ["-l", "-a", "-h"]. +Exec the <result> for the <command: "ls"> with ["-l", "-a", "-h"]. ``` This syntax clearly separates the command from its arguments, making code more readable. @@ -26,9 +26,9 @@ This syntax clearly separates the command from its arguments, making code more r The legacy syntax with full command in the `with` clause is still supported: ```aro -<Exec> the <result> for the <command> with "ls -la". -<Exec> the <listing> for the <files> with "find . -name '*.txt'". -<Exec> the <status> for the <check> with "git status". +Exec the <result> for the <command> with "ls -la". +Exec the <listing> for the <files> with "find . -name '*.txt'". +Exec the <status> for the <check> with "git status". ``` ### Using Variables @@ -36,11 +36,11 @@ The legacy syntax with full command in the `with` clause is still supported: Build commands dynamically with variables: ```aro -<Create> the <directory> with "/var/log". -<Exec> the <result> for the <command: "ls"> with "-la ${directory}". +Create the <directory> with "/var/log". +Exec the <result> for the <command: "ls"> with "-la ${directory}". -<Create> the <pattern> with "*.aro". -<Exec> the <files> for the <command: "find"> with [". ", "-name", "${pattern}"]. +Create the <pattern> with "*.aro". +Exec the <files> for the <command: "find"> with [". ", "-name", "${pattern}"]. ``` ## Result Object @@ -58,14 +58,14 @@ Every `<Exec>` action returns a structured result object: ### Accessing Result Fields ```aro -<Exec> the <result> for the <command> with "whoami". +Exec the <result> for the <command> with "whoami". (* Access individual fields *) -<Log> <result.output> to the <console>. -<Log> <result.exitCode> to the <console>. +Log <result.output> to the <console>. +Log <result.exitCode> to the <console>. (* Check for errors *) -<Log> <result.message> to the <console> when <result.error> = true. +Log <result.message> to the <console> when <result.error> = true. ``` ## Error Handling @@ -74,12 +74,12 @@ Every `<Exec>` action returns a structured result object: ```aro (Check Disk Space: System Monitor) { - <Exec> the <result> for the <disk-check> with "df -h". + Exec the <result> for the <disk-check> with "df -h". - <Log> <result.message> to the <console> when <result.error> = true. - <Return> an <Error: status> with <result> when <result.error> = true. + Log <result.message> to the <console> when <result.error> = true. + Return an <Error: status> with <result> when <result.error> = true. - <Return> an <OK: status> with <result>. + Return an <OK: status> with <result>. } ``` @@ -87,14 +87,14 @@ Every `<Exec>` action returns a structured result object: ```aro (Git Status: Version Control) { - <Exec> the <result> for the <git> with "git status --porcelain". + Exec the <result> for the <git> with "git status --porcelain". - <Log> "Not a git repository" to the <console> when <result.exitCode> != 0. - <Return> a <BadRequest: status> with { error: "Not a git repository" } when <result.exitCode> != 0. + Log "Not a git repository" to the <console> when <result.exitCode> != 0. + Return a <BadRequest: status> with { error: "Not a git repository" } when <result.exitCode> != 0. - <Return> an <OK: status> with { message: "Working tree clean" } when <result.output> is empty. + Return an <OK: status> with { message: "Working tree clean" } when <result.output> is empty. - <Return> an <OK: status> with { changes: <result.output> }. + Return an <OK: status> with { changes: <result.output> }. } ``` @@ -103,12 +103,12 @@ Every `<Exec>` action returns a structured result object: Commands that exceed the timeout return with `exitCode: -1`: ```aro -<Exec> the <result> for the <long-task> with { +Exec the <result> for the <long-task> with { command: "sleep 60", timeout: 5000 }. -<Log> "Command timed out" to the <console> when <result.exitCode> = -1. +Log "Command timed out" to the <console> when <result.exitCode> = -1. ``` ## Configuration Options @@ -116,7 +116,7 @@ Commands that exceed the timeout return with `exitCode: -1`: For advanced control, use object syntax: ```aro -<Exec> the <result> on the <system> with { +Exec the <result> on the <system> with { command: "npm install", workingDirectory: "/app", timeout: 60000, @@ -177,9 +177,9 @@ output: ```aro (Application-Start: Directory Lister) { - <Log> "Directory Lister" to the <console>. - <Exec> the <listing> for the <command> with "ls -la". - <Return> an <OK: status> for the <listing>. + Log "Directory Lister" to the <console>. + Exec the <listing> for the <command> with "ls -la". + Return an <OK: status> for the <listing>. } ``` @@ -187,17 +187,17 @@ output: ```aro (System Info: Status API) { - <Exec> the <hostname> for the <command: "hostname">. - <Exec> the <uptime> for the <command: "uptime">. - <Exec> the <memory> for the <command: "free"> with "-h". + Exec the <hostname> for the <command: "hostname">. + Exec the <uptime> for the <command: "uptime">. + Exec the <memory> for the <command: "free"> with "-h". - <Create> the <info> with { + Create the <info> with { hostname: <hostname.output>, uptime: <uptime.output>, memory: <memory.output> }. - <Return> an <OK: status> with <info>. + Return an <OK: status> with <info>. } ``` @@ -205,30 +205,30 @@ output: ```aro (Run Build: CI Pipeline) { - <Log> "Installing dependencies..." to the <console>. - <Exec> the <install> for the <npm> with { + Log "Installing dependencies..." to the <console>. + Exec the <install> for the <npm> with { command: "npm install", workingDirectory: "./app", timeout: 120000 }. - <Return> an <Error: status> with <install> when <install.error> = true. + Return an <Error: status> with <install> when <install.error> = true. - <Log> "Running tests..." to the <console>. - <Exec> the <test> for the <npm> with { + Log "Running tests..." to the <console>. + Exec the <test> for the <npm> with { command: "npm test", workingDirectory: "./app" }. - <Return> an <Error: status> with <test> when <test.error> = true. + Return an <Error: status> with <test> when <test.error> = true. - <Log> "Building..." to the <console>. - <Exec> the <build> for the <npm> with { + Log "Building..." to the <console>. + Exec the <build> for the <npm> with { command: "npm run build", workingDirectory: "./app" }. - <Return> an <OK: status> with <build>. + Return an <OK: status> with <build>. } ``` @@ -236,17 +236,17 @@ output: ```aro (Health Check: Monitoring) { - <Exec> the <curl> for the <health> with { + Exec the <curl> for the <health> with { command: "curl -s http://localhost:8080/health", timeout: 5000 }. - <Return> a <ServiceUnavailable: status> with { + Return a <ServiceUnavailable: status> with { service: "api", error: <curl.message> } when <curl.error> = true. - <Return> an <OK: status> with { healthy: true }. + Return an <OK: status> with { healthy: true }. } ``` @@ -254,17 +254,17 @@ output: ```aro (List Processes: Admin API) { - <Exec> the <processes> for the <list> with "ps aux | head -20". - <Return> an <OK: status> with <processes>. + Exec the <processes> for the <list> with "ps aux | head -20". + Return an <OK: status> with <processes>. } (Check Process: Admin API) { - <Extract> the <name> from the <queryParameters: name>. - <Exec> the <result> for the <check> with "pgrep -l ${name}". + Extract the <name> from the <queryParameters: name>. + Exec the <result> for the <check> with "pgrep -l ${name}". - <Return> an <OK: status> with { running: false, process: <name> } when <result.error> = true. + Return an <OK: status> with { running: false, process: <name> } when <result.error> = true. - <Return> an <OK: status> with { running: true, process: <name>, pids: <result.output> }. + Return an <OK: status> with { running: true, process: <name>, pids: <result.output> }. } ``` @@ -276,12 +276,12 @@ Be cautious when constructing commands from user input: ```aro (* DANGEROUS - user input directly in command *) -<Exec> the <result> for the <command> with "ls ${userInput}". +Exec the <result> for the <command> with "ls ${userInput}". (* SAFER - validate input first *) -<Validate> the <path> for the <userInput> against "^[a-zA-Z0-9_/.-]+$". -<Return> a <BadRequest: status> with "Invalid path characters" when <path> is not <valid>. -<Exec> the <result> for the <command> with "ls ${path}". +Validate the <path> for the <userInput> against "^[a-zA-Z0-9_/.-]+$". +Return a <BadRequest: status> with "Invalid path characters" when <path> is not <valid>. +Exec the <result> for the <command> with "ls ${path}". ``` ### Best Practices @@ -297,7 +297,7 @@ Be cautious when constructing commands from user input: Future versions may support sandboxing options: ```aro -<Exec> the <result> for the <command> with { +Exec the <result> for the <command> with { command: "npm install", sandbox: { network: false, diff --git a/Book/TheLanguageGuide/Chapter32-HTTPClient.md b/Book/TheLanguageGuide/Chapter32-HTTPClient.md index ff76ef38..53c15c07 100644 --- a/Book/TheLanguageGuide/Chapter32-HTTPClient.md +++ b/Book/TheLanguageGuide/Chapter32-HTTPClient.md @@ -16,8 +16,8 @@ Use `from` preposition to make GET requests: ```aro (* Simple GET request *) -<Create> the <url> with "https://api.example.com/users". -<Request> the <users> from the <url>. +Create the <url> with "https://api.example.com/users". +Request the <users> from the <url>. ``` ## POST Requests @@ -26,9 +26,9 @@ Use `to` preposition to make POST requests: ```aro (* POST with data from context *) -<Create> the <user-data> with { name: "Alice", email: "alice@example.com" }. -<Create> the <api-url> with "https://api.example.com/users". -<Request> the <result> to the <api-url> with <user-data>. +Create the <user-data> with { name: "Alice", email: "alice@example.com" }. +Create the <api-url> with "https://api.example.com/users". +Request the <result> to the <api-url> with <user-data>. ``` ## Other HTTP Methods @@ -37,13 +37,13 @@ Use `via` preposition with method specifier for PUT, DELETE, PATCH: ```aro (* PUT request *) -<Request> the <result> via PUT the <url> with <update-data>. +Request the <result> via PUT the <url> with <update-data>. (* DELETE request *) -<Request> the <result> via DELETE the <url>. +Request the <result> via DELETE the <url>. (* PATCH request *) -<Request> the <result> via PATCH the <url> with <partial-data>. +Request the <result> via PATCH the <url> with <partial-data>. ``` ## Config Object Syntax @@ -52,7 +52,7 @@ For full control over requests, use a config object with the `with { ... }` clau ```aro (* POST with custom headers and timeout *) -<Request> the <response> from the <api-url> with { +Request the <response> from the <api-url> with { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer token" }, body: <data>, @@ -60,7 +60,7 @@ For full control over requests, use a config object with the `with { ... }` clau }. (* GET with authorization header *) -<Request> the <protected-data> from the <api-url> with { +Request the <protected-data> from the <api-url> with { headers: { "Authorization": "Bearer my-token" } }. ``` @@ -88,15 +88,15 @@ The `<Request>` action automatically parses JSON responses. After a request, the | `result.isSuccess` | Boolean: true if status 200-299 | ```aro -<Create> the <api-url> with "https://api.example.com/users". -<Request> the <response> from the <api-url>. +Create the <api-url> with "https://api.example.com/users". +Request the <response> from the <api-url>. (* Access response metadata *) -<Extract> the <status> from the <response: statusCode>. -<Extract> the <is-ok> from the <response: isSuccess>. +Extract the <status> from the <response: statusCode>. +Extract the <is-ok> from the <response: isSuccess>. (* Access response body - response IS the parsed body *) -<Extract> the <first-user> from the <response: 0>. +Extract the <first-user> from the <response: 0>. ``` ## Complete Example @@ -105,14 +105,14 @@ The `<Request>` action automatically parses JSON responses. After a request, the (* Fetch weather data from Open-Meteo API *) (Application-Start: Weather Client) { - <Log> "Fetching weather..." to the <console>. + Log "Fetching weather..." to the <console>. - <Create> the <api-url> with "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true". - <Request> the <weather> from the <api-url>. + Create the <api-url> with "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true". + Request the <weather> from the <api-url>. - <Log> <weather> to the <console>. + Log <weather> to the <console>. - <Return> an <OK: status> for the <startup>. + Return an <OK: status> for the <startup>. } ``` diff --git a/Book/TheLanguageGuide/Chapter33-Concurrency.md b/Book/TheLanguageGuide/Chapter33-Concurrency.md index 8eefa864..1421f243 100644 --- a/Book/TheLanguageGuide/Chapter33-Concurrency.md +++ b/Book/TheLanguageGuide/Chapter33-Concurrency.md @@ -40,12 +40,12 @@ Inside a feature set, statements execute **synchronously** and **serially**: ```aro (Process Order: Order API) { - <Extract> the <data> from the <request: body>. (* 1. First *) - <Validate> the <data> for the <order-schema>. (* 2. Second *) - <Create> the <order> with <data>. (* 3. Third *) - <Store> the <order> in the <order-repository>. (* 4. Fourth *) - <Emit> to <Send Confirmation> with <order>. (* 5. Fifth *) - <Return> a <Created: status> with <order>. (* 6. Last *) + Extract the <data> from the <request: body>. (* 1. First *) + Validate the <data> for the <order-schema>. (* 2. Second *) + Create the <order> with <data>. (* 3. Third *) + Store the <order> in the <order-repository>. (* 4. Fourth *) + Emit to <Send Confirmation> with <order>. (* 5. Fifth *) + Return a <Created: status> with <order>. (* 6. Last *) } ``` @@ -72,12 +72,12 @@ ARO code: ```aro (Process Order: Order API) { - <Extract> the <data> from the <request: body>. - <Validate> the <data> for the <order-schema>. - <Create> the <order> with <data>. - <Store> the <order> in the <order-repository>. - <Emit> to <Send Confirmation> with <order>. - <Return> a <Created: status> with <order>. + Extract the <data> from the <request: body>. + Validate the <data> for the <order-schema>. + Create the <order> with <data>. + Store the <order> in the <order-repository>. + Emit to <Send Confirmation> with <order>. + Return a <Created: status> with <order>. } ``` @@ -116,11 +116,11 @@ The runtime performs **data-flow driven execution**: ```aro (Process Config: File Handler) { - <Open> the <config-file> from the <path>. (* 1. Starts file load *) - <Compute> the <hash> for the <request>. (* 2. Runs immediately *) - <Log> <request> to the <console>. (* 3. Runs immediately *) - <Parse> the <config> from the <config-file>. (* 4. Waits for file *) - <Return> an <OK: status> with <config>. + Open the <config-file> from the <path>. (* 1. Starts file load *) + Compute the <hash> for the <request>. (* 2. Runs immediately *) + Log <request> to the <console>. (* 3. Runs immediately *) + Parse the <config> from the <config-file>. (* 4. Waits for file *) + Return an <OK: status> with <config>. } ``` @@ -140,21 +140,21 @@ Feature sets can trigger other feature sets: ```aro (Create User: User API) { - <Extract> the <data> from the <request: body>. - <Create> the <user> with <data>. - <Store> the <user> in the <user-repository>. + Extract the <data> from the <request: body>. + Create the <user> with <data>. + Store the <user> in the <user-repository>. (* Triggers other feature sets asynchronously *) - <Emit> to <Send Welcome Email> with <user>. + Emit to <Send Welcome Email> with <user>. (* Continues immediately, doesn't wait for handler *) - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } (Send Welcome Email: Notifications) { - <Extract> the <email> from the <event: email>. - <Send> the <welcome-email> to the <email>. - <Return> an <OK: status>. + Extract the <email> from the <event: email>. + Send the <welcome-email> to the <email>. + Return an <OK: status>. } ``` @@ -187,7 +187,7 @@ By default, `for each` loops execute serially—one item after another: ```aro for each <number> in <numbers> { - <Log> <number> to the <console>. + Log <number> to the <console>. } ``` @@ -197,7 +197,7 @@ The `parallel for each` variant executes iterations concurrently: ```aro parallel for each <number> in <numbers> { - <Log> <number> to the <console>. + Log <number> to the <console>. } ``` @@ -231,7 +231,7 @@ By default, parallel loops use `System.coreCount` threads (matching your CPU's l ```aro (* Uses all available cores *) parallel for each <item> in <items> { - <Compute> the <result> from <item>. + Compute the <result> from <item>. } ``` @@ -240,7 +240,7 @@ You can override concurrency with the `with` clause: ```aro (* Limit to 4 concurrent iterations *) parallel for each <item> in <items> with <concurrency: 4> { - <Compute> the <result> from <item>. + Compute the <result> from <item>. } ``` @@ -277,19 +277,19 @@ From `Examples/ParallelForEach/main.aro`: ```aro (Application-Start: ForEach Demo) { - <Create> the <numbers> with [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. + Create the <numbers> with [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. - <Log> "=== Serial Iteration ===" to the <console>. + Log "=== Serial Iteration ===" to the <console>. for each <number> in <numbers> { - <Log> <number> to the <console>. + Log <number> to the <console>. } - <Log> "=== Parallel Iteration ===" to the <console>. + Log "=== Parallel Iteration ===" to the <console>. parallel for each <number> in <numbers> { - <Log> <number> to the <console>. + Log <number> to the <console>. } - <Return> an <OK: status> for the <demo>. + Return an <OK: status> for the <demo>. } ``` @@ -334,16 +334,16 @@ Output (example): ```aro (Application-Start: My API) { - <Start> the <http-server> on port 8080. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status>. + Start the <http-server> on port 8080. + Keepalive the <application> for the <events>. + Return an <OK: status>. } (* Each request triggers this independently *) (getUser: User API) { - <Extract> the <id> from the <pathParameters: id>. - <Retrieve> the <user> from the <user-repository> where id = <id>. - <Return> an <OK: status> with <user>. + Extract the <id> from the <pathParameters: id>. + Retrieve the <user> from the <user-repository> where id = <id>. + Return an <OK: status> with <user>. } ``` @@ -351,17 +351,17 @@ Output (example): ```aro (Application-Start: Echo Server) { - <Start> the <socket-server> on port 9000. - <Keepalive> the <application> for the <events>. - <Return> an <OK: status>. + Start the <socket-server> on port 9000. + Keepalive the <application> for the <events>. + Return an <OK: status>. } (* Each client message triggers this independently *) (Handle Data: Socket Event Handler) { - <Extract> the <data> from the <event: data>. - <Extract> the <connection> from the <event: connection>. - <Send> the <data> to the <connection>. - <Return> an <OK: status>. + Extract the <data> from the <event: data>. + Extract the <connection> from the <event: connection>. + Send the <data> to the <connection>. + Return an <OK: status>. } ``` @@ -369,18 +369,18 @@ Output (example): ```aro (Application-Start: File Watcher) { - <Watch> the <directory> for the <changes> with "./watched". - <Keepalive> the <application> for the <events>. - <Return> an <OK: status>. + Watch the <directory> for the <changes> with "./watched". + Keepalive the <application> for the <events>. + Return an <OK: status>. } (* Each file change triggers this independently *) (Handle File Change: File Event Handler) { - <Extract> the <path> from the <event: path>. - <Extract> the <type> from the <event: type>. - <Compute> the <message> from "File " + <path> + " " + <type>. - <Log> <message> to the <console>. - <Return> an <OK: status>. + Extract the <path> from the <event: path>. + Extract the <type> from the <event: type>. + Compute the <message> from "File " + <path> + " " + <type>. + Log <message> to the <console>. + Return an <OK: status>. } ``` diff --git a/Book/TheLanguageGuide/Chapter34-ContextResponses.md b/Book/TheLanguageGuide/Chapter34-ContextResponses.md index 5052c5b5..b89951a7 100644 --- a/Book/TheLanguageGuide/Chapter34-ContextResponses.md +++ b/Book/TheLanguageGuide/Chapter34-ContextResponses.md @@ -20,8 +20,8 @@ When you run ARO from the command line, output is formatted for readability: ```aro (Application-Start: Example) { - <Log> "Hello, World!" to the <console>. - <Return> an <OK: status> for the <startup>. + Log "Hello, World!" to the <console>. + Return an <OK: status> for the <startup>. } ``` @@ -67,9 +67,9 @@ The runtime automatically detects context: ```aro (getUser: User API) { - <Retrieve> the <user> from the <user-repository> where id = <id>. - <Log> "User retrieved" to the <console>. - <Return> an <OK: status> with <user>. + Retrieve the <user> from the <user-repository> where id = <id>. + Log "User retrieved" to the <console>. + Return an <OK: status> with <user>. } ``` @@ -126,7 +126,7 @@ The runtime automatically detects context: The `<Log>` action respects output context: ```aro -<Log> <value> to the <console>. +Log <value> to the <console>. ``` - **Human**: `[FeatureSetName] value` @@ -138,7 +138,7 @@ The `<Log>` action respects output context: The `<Return>` action sets the response, which is formatted based on context: ```aro -<Return> an <OK: status> with <result>. +Return an <OK: status> with <result>. ``` --- diff --git a/Book/TheLanguageGuide/Chapter35-TypeSystem.md b/Book/TheLanguageGuide/Chapter35-TypeSystem.md index d24603fc..00f42201 100644 --- a/Book/TheLanguageGuide/Chapter35-TypeSystem.md +++ b/Book/TheLanguageGuide/Chapter35-TypeSystem.md @@ -25,23 +25,23 @@ ARO has two built-in collection types: ### List Examples ```aro -<Create> the <numbers: List<Integer>> with [1, 2, 3]. -<Create> the <names: List<String>> with ["Alice", "Bob", "Charlie"]. +Create the <numbers: List<Integer>> with [1, 2, 3]. +Create the <names: List<String>> with ["Alice", "Bob", "Charlie"]. for each <number> in <numbers> { - <Log> <number> to the <console>. + Log <number> to the <console>. } ``` ### Map Examples ```aro -<Create> the <config: Map<String, Integer>> with { +Create the <config: Map<String, Integer>> with { port: 8080, timeout: 30 }. -<Extract> the <port> from the <config: port>. +Extract the <port> from the <config: port>. ``` ## Complex Types from OpenAPI @@ -94,15 +94,15 @@ components: ```aro (Create User: User Management) { - <Extract> the <data> from the <request: body>. + Extract the <data> from the <request: body>. (* User type comes from openapi.yaml *) - <Create> the <user: User> with <data>. + Create the <user: User> with <data>. (* Access fields defined in the schema *) - <Log> <user: name> to the <console>. + Log <user: name> to the <console>. - <Return> a <Created: status> with <user>. + Return a <Created: status> with <user>. } ``` @@ -137,9 +137,9 @@ Type annotations are optional but recommended when: ```aro (* Recommended: explicit types for external data *) -<Extract> the <userId: String> from the <request: body>. -<Extract> the <items: List<OrderItem>> from the <request: body>. -<Retrieve> the <user: User> from the <user-repository> where id = <userId>. +Extract the <userId: String> from the <request: body>. +Extract the <items: List<OrderItem>> from the <request: body>. +Retrieve the <user: User> from the <user-repository> where id = <userId>. ``` ## Type Inference @@ -147,11 +147,11 @@ Type annotations are optional but recommended when: Types are inferred from literals and expressions: ```aro -<Create> the <count> with 42. (* count: Integer *) -<Create> the <name> with "John". (* name: String *) -<Create> the <active> with true. (* active: Boolean *) -<Create> the <price> with 19.99. (* price: Float *) -<Create> the <items> with [1, 2, 3]. (* items: List<Integer> *) +Create the <count> with 42. (* count: Integer *) +Create the <name> with "John". (* name: String *) +Create the <active> with true. (* active: Boolean *) +Create the <price> with 19.99. (* price: Float *) +Create the <items> with [1, 2, 3]. (* items: List<Integer> *) ``` ## No Optionals @@ -164,12 +164,12 @@ The runtime throws a descriptive error: ```aro (Get User: API) { - <Extract> the <id> from the <pathParameters: id>. - <Retrieve> the <user: User> from the <user-repository> where id = <id>. + Extract the <id> from the <pathParameters: id>. + Retrieve the <user: User> from the <user-repository> where id = <id>. (* If user doesn't exist, runtime throws: *) (* "Cannot retrieve the user from the user-repository where id = 123" *) - <Return> an <OK: status> with <user>. + Return an <OK: status> with <user>. } ``` @@ -188,8 +188,8 @@ console.log(user.name); ARO code: ```aro -<Retrieve> the <user> from the <user-repository> where id = <id>. -<Log> <user: name> to the <console>. +Retrieve the <user> from the <user-repository> where id = <id>. +Log <user: name> to the <console>. ``` The runtime error message IS the error handling. See the Error Handling chapter for more details. diff --git a/Book/TheLanguageGuide/Chapter36-Dates.md b/Book/TheLanguageGuide/Chapter36-Dates.md index 6365b21f..a7065893 100644 --- a/Book/TheLanguageGuide/Chapter36-Dates.md +++ b/Book/TheLanguageGuide/Chapter36-Dates.md @@ -19,7 +19,7 @@ The foundation of ARO's temporal model is UTC (Coordinated Universal Time). All ARO provides a special variable that exists without declaration: `<now>`. This magic variable always resolves to the current UTC timestamp: ```aro -<Log> <now> to the <console>. +Log <now> to the <console>. ``` The output follows ISO 8601 format: `2025-12-29T15:20:49Z`. The trailing `Z` indicates UTC. This format is unambiguous, sortable as text, and universally understood by APIs and databases. @@ -42,12 +42,12 @@ Unlike regular variables, `<now>` needs no prior binding. It exists in every fea Dates contain structured information: years, months, days, hours, minutes, seconds. ARO exposes these components through qualifiers: ```aro -<Extract> the <year> from the <now: year>. -<Extract> the <month> from the <now: month>. -<Extract> the <day> from the <now: day>. -<Extract> the <hour> from the <now: hour>. -<Extract> the <minute> from the <now: minute>. -<Extract> the <second> from the <now: second>. +Extract the <year> from the <now: year>. +Extract the <month> from the <now: month>. +Extract the <day> from the <now: day>. +Extract the <hour> from the <now: hour>. +Extract the <minute> from the <now: minute>. +Extract the <second> from the <now: second>. ``` Each extraction produces an integer. The month is 1-indexed (January = 1, December = 12). The hour uses 24-hour format (0-23). The day of week follows ISO convention: Sunday = 1, Monday = 2, through Saturday = 7. @@ -97,7 +97,7 @@ Additional properties include `timestamp` (Unix epoch seconds), `iso` (the full External systems send dates as strings. Users enter dates in forms. Configuration files specify dates in text. ARO parses these into proper date objects: ```aro -<Compute> the <deadline: date> from "2025-12-31T23:59:59Z". +Compute the <deadline: date> from "2025-12-31T23:59:59Z". ``` The qualifier `: date` tells Compute to interpret the input string as an ISO 8601 date. Once parsed, the result behaves like any other date—you can extract components, calculate distances, or compare it against other dates. @@ -118,7 +118,7 @@ The parser is strict. Invalid dates produce errors rather than surprising interp Dates need to be displayed to users, and different contexts call for different formats. Europeans expect day-month-year. Americans expect month-day-year. Formal documents want full month names. Log files want compact timestamps. ```aro -<Compute> the <display: format> from <deadline> with "MMMM dd, yyyy". +Compute the <display: format> from <deadline> with "MMMM dd, yyyy". ``` The second parameter is a format pattern. Common patterns include: @@ -141,10 +141,10 @@ The pattern language follows standard conventions. Four `y`s mean four-digit yea Business logic often involves relative dates. "Tomorrow" is one day from now. "Next week" is seven days from now. "The booking expires in 24 hours." These relative calculations are expressed through offset qualifiers: ```aro -<Compute> the <tomorrow: +1d> from <now>. -<Compute> the <yesterday: -1d> from <now>. -<Compute> the <next-week: +7d> from <now>. -<Compute> the <expires: +24h> from <created-at>. +Compute the <tomorrow: +1d> from <now>. +Compute the <yesterday: -1d> from <now>. +Compute the <next-week: +7d> from <now>. +Compute the <expires: +24h> from <created-at>. ``` The offset consists of a sign (`+` or `-`), a number, and a unit. Available units: @@ -162,8 +162,8 @@ The offset consists of a sign (`+` or `-`), a number, and a unit. Available unit Offsets can be chained by computing from an already-offset date: ```aro -<Compute> the <next-month: +1M> from <now>. -<Compute> the <next-month-plus-week: +1w> from <next-month>. +Compute the <next-month: +1M> from <now>. +Compute the <next-month-plus-week: +1w> from <next-month>. ``` --- @@ -173,23 +173,23 @@ Offsets can be chained by computing from an already-offset date: Many business concepts span periods: fiscal quarters, subscription terms, booking windows, sale periods. ARO represents these as date ranges: ```aro -<Create> the <q4: date-range> from <oct-first> to <dec-thirty-first>. +Create the <q4: date-range> from <oct-first> to <dec-thirty-first>. ``` Ranges expose useful properties: ```aro -<Extract> the <duration: days> from <q4>. -<Extract> the <duration: hours> from <q4>. -<Extract> the <start> from the <q4: start>. -<Extract> the <end> from the <q4: end>. +Extract the <duration: days> from <q4>. +Extract the <duration: hours> from <q4>. +Extract the <start> from the <q4: start>. +Extract the <end> from the <q4: end>. ``` The range membership operator `in` enables temporal queries in when clauses: ```aro when <order-date> in <sale-period> { - <Compute> the <discount> from <price> * 0.2. + Compute the <discount> from <price> * 0.2. } ``` @@ -201,11 +201,11 @@ Dates can be compared using `before` and `after` operators in when clauses: ```aro when <booking-date> before <deadline> { - <Log> "Booking accepted" to the <console>. + Log "Booking accepted" to the <console>. } when <event-date> after <now> { - <Log> "Event is upcoming" to the <console>. + Log "Event is upcoming" to the <console>. } ``` @@ -218,9 +218,9 @@ These temporal comparisons read naturally and express intent clearly. The runtim How many days until the deadline? How many hours since the last update? These questions require calculating the distance between two dates: ```aro -<Compute> the <remaining: distance> from <now> to <deadline>. -<Extract> the <days-left> from the <remaining: days>. -<Extract> the <hours-left> from the <remaining: hours>. +Compute the <remaining: distance> from <now> to <deadline>. +Extract the <days-left> from the <remaining: days>. +Extract the <hours-left> from the <remaining: hours>. ``` The distance operation captures the interval between two points in time. You can then extract that distance in whatever units make sense for your domain—days for project timelines, hours for SLA tracking, seconds for performance metrics. @@ -232,16 +232,16 @@ The distance operation captures the interval between two points in time. You can Some events repeat: weekly meetings, monthly reports, annual reviews. ARO supports recurrence patterns: ```aro -<Create> the <standup: recurrence> with "every monday". -<Create> the <monthly-report: recurrence> with "every month". -<Create> the <biweekly: recurrence> with "every 2 weeks". +Create the <standup: recurrence> with "every monday". +Create the <monthly-report: recurrence> with "every month". +Create the <biweekly: recurrence> with "every 2 weeks". ``` From a recurrence, you can extract the next or previous occurrence: ```aro -<Extract> the <next-meeting> from the <standup: next>. -<Extract> the <last-meeting> from the <standup: previous>. +Extract the <next-meeting> from the <standup: next>. +Extract the <last-meeting> from the <standup: previous>. ``` Supported patterns include: diff --git a/Book/TheLanguageGuide/Chapter37-Metrics.md b/Book/TheLanguageGuide/Chapter37-Metrics.md index 63f521a0..241df174 100644 --- a/Book/TheLanguageGuide/Chapter37-Metrics.md +++ b/Book/TheLanguageGuide/Chapter37-Metrics.md @@ -7,7 +7,7 @@ ARO automatically tracks execution metrics for all feature sets. The `<metrics>` Access metrics like any variable: ```aro -<Log> the <metrics> to the <console>. +Log the <metrics> to the <console>. ``` This outputs all collected metrics in a readable format. @@ -17,10 +17,10 @@ This outputs all collected metrics in a readable format. Use qualifiers to control output format: ```aro -<Log> the <metrics: plain> to the <console>. (* Full details *) -<Log> the <metrics: short> to the <console>. (* One-liner *) -<Log> the <metrics: table> to the <console>. (* ASCII table *) -<Log> the <metrics: prometheus> to the <console>. (* For monitoring *) +Log the <metrics: plain> to the <console>. (* Full details *) +Log the <metrics: short> to the <console>. (* One-liner *) +Log the <metrics: table> to the <console>. (* ASCII table *) +Log the <metrics: prometheus> to the <console>. (* For monitoring *) ``` | Qualifier | Output | @@ -113,9 +113,9 @@ Print metrics at shutdown to see what ran: ```aro (Application-End: Success) { - <Log> "=== Final Metrics ===" to the <console>. - <Log> the <metrics: table> to the <console>. - <Return> an <OK: status> for the <shutdown>. + Log "=== Final Metrics ===" to the <console>. + Log the <metrics: table> to the <console>. + Return an <OK: status> for the <shutdown>. } ``` @@ -124,7 +124,7 @@ Print metrics at shutdown to see what ran: A one-liner during execution: ```aro -<Log> the <metrics: short> to the <console>. +Log the <metrics: short> to the <console>. ``` Output: @@ -138,7 +138,7 @@ Expose metrics for monitoring systems: ```aro (getMetrics: Monitoring API) { - <Return> an <OK: status> with <metrics: prometheus>. + Return an <OK: status> with <metrics: prometheus>. } ``` @@ -166,9 +166,9 @@ Compare feature set performance: ```aro (analyzePerformance: Admin API) { - <Log> "Performance Analysis:" to the <console>. - <Log> the <metrics: table> to the <console>. - <Return> an <OK: status> with <metrics: plain>. + Log "Performance Analysis:" to the <console>. + Log the <metrics: table> to the <console>. + Return an <OK: status> with <metrics: plain>. } ``` diff --git a/Book/TheLanguageGuide/Chapter38-Templates.md b/Book/TheLanguageGuide/Chapter38-Templates.md index 40741b64..4fcb5b96 100644 --- a/Book/TheLanguageGuide/Chapter38-Templates.md +++ b/Book/TheLanguageGuide/Chapter38-Templates.md @@ -55,18 +55,18 @@ Execution blocks are delimited by `{{ }}` and contain ARO statements. Any valid ```aro (* templates/greeting.tpl *) -Hello, {{ <Print> <user: name> to the <template>. }}! +Hello, {{ Print <user: name> to the <template>. }}! Welcome to our service. Your account was created on -{{ <Print> <user: createdAt> to the <template>. }}. +{{ Print <user: createdAt> to the <template>. }}. ``` Multiple statements can appear in a single block: ```aro {{ - <Compute> the <total> from <price> * <quantity>. - <Print> <total> to the <template>. + Compute the <total> from <price> * <quantity>. + Print <total> to the <template>. }} ``` @@ -75,9 +75,9 @@ Multiple statements can appear in a single block: The `<Print>` action with `to the <template>` writes output to the template's result buffer: ```aro -<Print> <value> to the <template>. -<Print> "literal text" to the <template>. -<Print> <price> * 1.1 to the <template>. +Print <value> to the <template>. +Print "literal text" to the <template>. +Print <price> * 1.1 to the <template>. ``` ## 38.3 Variable Interpolation Shorthand @@ -86,7 +86,7 @@ For simple variable output, ARO provides a shorthand syntax. When an execution b ```aro (* Full syntax *) -{{ <Print> <username> to the <template>. }} +{{ Print <username> to the <template>. }} (* Shorthand - equivalent to above *) {{ <username> }} @@ -112,18 +112,18 @@ The `<Transform>` action renders a template with the current context: ```aro (Send Welcome Email: User Notification) { - <Extract> the <user> from the <event: user>. + Extract the <user> from the <event: user>. (* Render the email template *) - <Transform> the <email-body> from the <template: welcome.tpl>. + Transform the <email-body> from the <template: welcome.tpl>. (* Send the email with the rendered content *) - <Send> the <email> to the <user: email> with { + Send the <email> to the <user: email> with { subject: "Welcome!", body: <email-body> }. - <Return> an <OK: status> for the <notification>. + Return an <OK: status> for the <notification>. } ``` @@ -221,14 +221,14 @@ Use `when` guards for conditional output: ```aro (* Conditional print *) -{{ <Print> "Premium Member" to the <template> when <user: isPremium>. }} +{{ Print "Premium Member" to the <template> when <user: isPremium>. }} (* With else using match *) {{ match <user: tier> { - "gold" => <Print> "Gold Member" to the <template>. - "silver" => <Print> "Silver Member" to the <template>. - _ => <Print> "Standard Member" to the <template>. + "gold" => Print "Gold Member" to the <template>. + "silver" => Print "Silver Member" to the <template>. + _ => Print "Standard Member" to the <template>. } }} ``` @@ -237,7 +237,7 @@ For conditional sections, combine with for-each over a filtered collection or us ```aro {{ for each <item> in <items> { }} -{{ <Print> <item: name> to the <template> when <item: isActive>. }} +{{ Print <item: name> to the <template> when <item: isActive>. }} {{ } }} ``` @@ -253,13 +253,13 @@ The `<Include>` action embeds one template inside another: <title>{{ <page: title> }} - {{ the . }} + {{ Include the . }}
{{ }}
- {{ the . }} + {{ Include the . }} ``` @@ -269,7 +269,7 @@ The `` action embeds one template inside another: Use the `with` clause to pass additional variables: ```aro -{{ the with { +{{ Include the with { user: , showEmail: true }. }} @@ -290,7 +290,7 @@ This pattern enables component-style template composition: (* templates/form.tpl *)
- {{ the with { + {{ Include the with { class: "primary", type: "submit", label: "Subscribe" @@ -321,12 +321,12 @@ Use with the Transform action: ```aro (Render Event Cards: Calendar Display) { - the from the + Retrieve the from the where date >= and date <= . - the from the . + Transform the from the . - an with . + Return an with . } ``` @@ -350,18 +350,18 @@ For displaying upcoming dates like birthdays, deadlines, or appointments: ```aro (Show Upcoming Dates: Dashboard) { - the from the + Retrieve the from the where dueDate >= . (* Compute days until each deadline *) {{ for each in { }} - the from - . + Compute the from - . (* Add to processed list *) {{ } }} - the from the . + Transform the from the . - an with . + Return an with . } ``` @@ -401,19 +401,19 @@ Here's a complete example showing a feature set that renders a user profile page ```aro (* main.aro *) (Application-Start: Profile App) { - the with . - the for the . - an for the . + Start the with . + Keepalive the for the . + Return an for the . } (getUserProfile: Profile API) { - the from the . - the from the where id = . - the from the where authorId = . + Extract the from the . + Retrieve the from the where id = . + Retrieve the from the where authorId = . - the from the . + Transform the from the . - an with . + Return an with . } ``` @@ -430,7 +430,7 @@ Here's a complete example showing a feature set that renders a user profile page
- {{ the . }} + {{ Include the . }}

{{ }}

{{ }}

@@ -444,7 +444,7 @@ Here's a complete example showing a feature set that renders a user profile page {{ } }} - {{ the . }} + {{ Include the . }}
@@ -476,13 +476,13 @@ Do computations and data preparation in your feature set, not in templates. Temp ```aro (* Good: Prepare data first *) (Render Dashboard: Admin View) { - the from the . - the from . - the from where isActive = true. - the from . + Retrieve the from the . + Compute the from . + Compute the from where isActive = true. + Compute the from . - the from the . - an with . + Transform the from the . + Return an with . } (* Template just displays prepared values *) @@ -497,10 +497,10 @@ Since templates access variables by name, use descriptive names that make templa ```aro (* Clear what each variable represents *) - the from the . +Transform the from the . (* Instead of generic names *) - the from the . +Transform the from the . ``` ### Handle Missing Data Gracefully @@ -509,8 +509,8 @@ Consider what happens when optional data is missing: ```aro (* Template with conditional rendering *) -{{ to the