Conversation
…tion of literal types in assignments
- docs/instructions.md: Guide covering build system, architectural layers, instrument anatomy, audio callback patterns, and codebase conventions - docs/names.md: Naming philosophy and guidelines for the project - README.md: Link new docs from the Instructions section
Updated image source in README to a new URL.
There was a problem hiding this comment.
Pull request overview
This PR is a broad “atto” refactor/rename plus infrastructure work that expands the core language/compiler/editor with symbol/literal/metatype support, shadow nodes, and a new editor pane architecture.
Changes:
- Renames/realigns build + tooling from “nano” to “atto” (targets, deps, file extensions, docs).
- Adds new core language capabilities (symbols/metatypes/literals, graph indexing, shadow nodes, symbol table) and updates inference/type utilities accordingly.
- Introduces new editor components (Editor2 pane, nets editor, shared editor state, style system) and embeds Liberation Mono font via CMake.
Reviewed changes
Copilot reviewed 59 out of 85 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/attoflow/nets_editor.h | Adds a nets-focused editor pane interface for named nets layout/hover/hit-testing. |
| src/attoflow/main.cpp | Switches the entry include to the new window API. |
| src/attoflow/fonts/LICENSE-LiberationFonts | Adds font license text for bundled Liberation font. |
| src/attoflow/editor_style.h | Introduces centralized style constants for Editor2 rendering. |
| src/attoflow/editor_style.cpp | Implements Editor2 style defaults and a global style instance. |
| src/attoflow/editor_pane.h | Adds a small interface for editor panes (type + draw + GraphBuilder access). |
| src/attoflow/editor2.h | Adds Editor2Pane and per-item editor impls implementing graph editor observer interfaces. |
| src/attoflow/atto_editor_shared_state.h | Adds shared editor state (node multi-selection) across panes. |
| src/attoc/main.cpp | Renames inputs/paths from .nano to .atto and updates error reporting & codegen args. |
| src/attoc/codegen.h | Adds GraphIndex usage, updates find_nodes signature, and adds emit_bang_next hook. |
| src/atto/types.h | Extends TypeKind/TypeExpr for symbols/metatypes/literals and updates type utilities. |
| src/atto/types.cpp | Extends type parsing/printing/compatibility for structs, literals, symbols, metatypes. |
| src/atto/type_utils.h | Adds decl name/type extraction helpers and upgrades pin reconciliation to PinVec + resolved types. |
| src/atto/type_utils.cpp | Implements decl extraction via shadow nodes and updates type-based pin resolution to NodeTypeID/PinVec. |
| src/atto/symbol_table.h | Adds a symbol table abstraction for builtins and declarations. |
| src/atto/symbol_table.cpp | Implements builtin symbol population and basic symbol table operations. |
| src/atto/shadow.h | Adds APIs for generating/removing/updating shadow expr nodes and rebuilding inline display. |
| src/atto/shadow.cpp | Implements shadow node generation, cleanup, and inline display reconstruction logic. |
| src/atto/serial.h | Introduces .atto load/save API surface and metadata load/save helpers. |
| src/atto/node_types.h | Adds NodeTypeID enum + descriptor tables and lookup helpers in a header. |
| src/atto/model.h | Introduces updated core model (FlowGraph/FlowNode/FlowPin) with PinVec + parsing metadata. |
| src/atto/inference.h | Adds GraphIndex + SymbolTable to inference and new deref/shadow-related phases. |
| src/atto/graph_index.h | Adds an O(1) lookup index over graph nodes/pins/links for inference/codegen. |
| src/atto/graph_index.cpp | Implements GraphIndex rebuild and common lookup helpers. |
| src/atto/graph_editor_interfaces.h | Adds editor observer interfaces (graph/node/net + arg editors) without UI deps. |
| src/atto/graph_builder.h | Adds the GraphBuilder layer (sentinels, observers, batching, parsed args) for editor semantics. |
| src/atto/expr.h | Extends expression kinds toward symbols/literals/structs/namespaces/type apply and adds symbol_table hook. |
| src/atto/args.h | Adds split_args API and minor include changes; keeps legacy parse_args wrapper. |
| src/atto/args.cpp | Updates tokenization for braces, adds FlowNode::parse_args, and implements split_args. |
| docs/thinking.md | Adds design rationale and philosophy documentation. |
| docs/style.md | Adds a style guide for code + language/editor conventions. |
| docs/podcasts/notes/introducing-orgasm.md | Adds long-form podcast notes document. |
| docs/podcasts/introducing-orgasm.md | Adds a short podcast index page and links to audio/video. |
| docs/patterns.md | Adds a patterns catalog and architectural idioms documentation. |
| docs/names.md | Adds naming philosophy documentation and rename history. |
| docs/differential.md | Adds documentation on “differential” computation/dev practices in the project. |
| docs/coding.md | Adds coding conventions documentation for the C++ codebase. |
| docs/changelog.md | Adds a project changelog / phase history document. |
| docs/architecture.md | Adds a full architecture overview document. |
| cmake/AttoDeps.cmake | Renames deps helper and updates the ImGui toggle variable name. |
| attostd/imgui.atto | Updates stdlib module header comment to attolang naming. |
| attostd/gui.atto | Updates stdlib module header comment to attolang naming. |
| README.md | Rebrands to “Organic Assembler” and updates links/docs/podcast references. |
| CMakeLists.txt | Renames targets (attolang/attoc/attoflow), adds new core sources, embeds Liberation Mono font. |
| .github/workflows/ci.yml | Changes CI triggers to run on stable/develop instead of main. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (peek() == '\\') { advance(); if (!eof()) value_str += advance(); } | ||
| else value_str += advance(); | ||
| } | ||
| if (!eof()) advance(); // consume closing " |
There was a problem hiding this comment.
The string branch accepts unterminated string literals inside literal<..., "...> without setting an error (it just reaches eof() and continues). This will silently produce malformed types and make diagnostics confusing. Make unterminated string detection explicit (e.g., if eof() before finding the closing quote, set error and return nullptr).
| if (peek() == '\\') { advance(); if (!eof()) value_str += advance(); } | |
| else value_str += advance(); | |
| } | |
| if (!eof()) advance(); // consume closing " | |
| if (peek() == '\\') { | |
| advance(); | |
| if (!eof()) value_str += advance(); | |
| } else { | |
| value_str += advance(); | |
| } | |
| } | |
| if (eof()) { | |
| error = "Unterminated string literal in literal<> type"; | |
| return nullptr; | |
| } | |
| advance(); // consume closing " |
| // literal<T, V> — compile-time literal value | ||
| if (name == "literal") { | ||
| skip_ws(); | ||
| if (peek() == '<') { | ||
| advance(); | ||
| auto domain = parse(); | ||
| if (!domain) return nullptr; | ||
| skip_ws(); | ||
| if (peek() == ',') { | ||
| advance(); | ||
| skip_ws(); | ||
| // Parse the value — could be a string, number, or identifier | ||
| std::string value_str; | ||
| if (peek() == '"') { | ||
| // String value | ||
| advance(); // consume opening " | ||
| while (!eof() && peek() != '"') { | ||
| if (peek() == '\\') { advance(); if (!eof()) value_str += advance(); } | ||
| else value_str += advance(); | ||
| } | ||
| if (!eof()) advance(); // consume closing " | ||
| domain->literal_value = "\"" + value_str + "\""; | ||
| } else if (peek() == '-' || std::isdigit(peek())) { | ||
| // Numeric value | ||
| if (peek() == '-') { value_str += advance(); } | ||
| while (!eof() && (std::isdigit(peek()) || peek() == '.' || peek() == 'f')) | ||
| value_str += advance(); | ||
| domain->literal_value = value_str; | ||
| } else if (peek() == '?') { | ||
| // Unvalued literal: literal<T,?> | ||
| advance(); | ||
| domain->is_unvalued_literal = true; | ||
| } else { | ||
| // Identifier value (symbol name, bool, etc.) | ||
| value_str = read_ident(); | ||
| domain->literal_value = value_str; | ||
| } | ||
| } | ||
| skip_ws(); | ||
| if (!expect('>')) return nullptr; | ||
| domain->is_generic = domain->is_generic; // preserve generic flag from domain | ||
| return domain; | ||
| } | ||
| // bare "literal" without <> is an error | ||
| error = "literal requires <type, value> parameters"; | ||
| return nullptr; | ||
| } |
There was a problem hiding this comment.
literal without a comma/value currently parses successfully (it just skips the comma block and returns domain), but the error message says literal requires <type, value>. This inconsistency will allow malformed types to slip through. Consider requiring a comma/value (or interpreting it as literal<Domain,?> explicitly) and erroring otherwise.
| } | ||
| skip_ws(); | ||
| if (!expect('>')) return nullptr; | ||
| domain->is_generic = domain->is_generic; // preserve generic flag from domain |
There was a problem hiding this comment.
This assignment is a no-op and likely leftover from an earlier refactor. Removing it would reduce confusion; if the intent is to preserve some other flag/value, assign the correct field explicitly.
| domain->is_generic = domain->is_generic; // preserve generic flag from domain |
| if (c == '{') { | ||
| brace_depth++; | ||
| current += c; | ||
| continue; | ||
| } | ||
| if (c == '}') { | ||
| brace_depth--; | ||
| current += c; | ||
| continue; | ||
| } | ||
| if (c == ' ' && paren_depth == 0 && brace_depth == 0) { |
There was a problem hiding this comment.
tokenize_args() now tracks brace_depth but never validates it. If the input contains an extra '}', brace_depth becomes negative and the splitter logic may behave incorrectly without any error signal. Since split_args() explicitly reports mismatches, consider adding a similar guard here (e.g., clamp + error handling) or route callers that need correctness to split_args().
| static const FlowNode* find_shadow_source(const FlowNode& node, const std::string& pin_name, const FlowGraph& graph) { | ||
| // Find the pin | ||
| std::string pin_id; | ||
| for (auto& p : node.inputs) { | ||
| if (p->name == pin_name) { pin_id = p->id; break; } | ||
| } | ||
| if (pin_id.empty()) return nullptr; | ||
| // Find the link TO this pin | ||
| for (auto& link : graph.links) { | ||
| if (link.to_pin == pin_id) { | ||
| // Find the source node | ||
| auto dot = link.from_pin.find('.'); | ||
| if (dot == std::string::npos) continue; | ||
| std::string src_guid = link.from_pin.substr(0, dot); | ||
| for (auto& n : graph.nodes) { | ||
| if (n.guid == src_guid) return &n; | ||
| } | ||
| } | ||
| } | ||
| return nullptr; | ||
| } |
There was a problem hiding this comment.
find_shadow_source() is O(#links * #nodes) per call due to nested scans. Since get_decl_name/get_decl_type_str may be called repeatedly across nodes, this can become a hotspot. Consider using GraphIndex (already introduced) to map pin→source pin/node in O(1), or precomputing a guid lookup map once per resolve_type_based_pins() run.
| fs::path nano_project_abs = fs::absolute(fs::path(input_arg)); | ||
| std::string nano_project_str = nano_project_abs.string(); | ||
| std::replace(nano_project_str.begin(), nano_project_str.end(), '\\', '/'); | ||
| // Pass the project directory (not the .atto file) — nanoc expects a folder |
There was a problem hiding this comment.
This comment still refers to 'nanoc' after the rename to attoc. Updating it to 'attoc' would avoid confusion when reading the compiler pipeline.
| // Pass the project directory (not the .atto file) — nanoc expects a folder | |
| // Pass the project directory (not the .atto file) — attoc expects a folder |
| branches: [stable, develop] | ||
| pull_request: | ||
| branches: [main] | ||
| branches: [stable, develop] |
There was a problem hiding this comment.
CI no longer runs for pushes/PRs targeting 'main'. If the default branch is still main (the workflow previously targeted it), this effectively disables CI for the primary branch. Consider including main as well (or confirm the repo default branch has been migrated to stable/develop).
| An Operating System for Instruments (Όργανα), written in attolang. Instruments are multimodal dataflow programs — authored as node graphs possibly using the **attoflow** editor, compiled, and run in real time. | ||
|
|
||
|  | ||
| Each instrument is a self-contained `.atto` program that defines its Functionality. The System compiles these programs runs them with hot-reload support. |
There was a problem hiding this comment.
This sentence has capitalization inconsistencies and a missing conjunction/punctuation, which makes it harder to read.
| Each instrument is a self-contained `.atto` program that defines its Functionality. The System compiles these programs runs them with hot-reload support. | |
| Each instrument is a self-contained `.atto` program that defines its functionality. The system compiles these programs and runs them with hot-reload support. |
wip