{"id":15060533,"url":"https://github.com/fpw/yamas","last_synced_at":"2025-06-22T07:38:20.735Z","repository":{"id":204569858,"uuid":"707956521","full_name":"fpw/yamas","owner":"fpw","description":"Yamas: Yet Another Macro Assembler (for the PDP-8)","archived":false,"fork":false,"pushed_at":"2024-03-12T20:52:11.000Z","size":510,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-17T07:49:25.506Z","etag":null,"topics":["assembler","pdp-8","retrocomputing","vintage-computers"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fpw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-21T04:55:17.000Z","updated_at":"2025-03-17T01:07:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"6adff129-9916-43c5-9839-0b3560430652","html_url":"https://github.com/fpw/yamas","commit_stats":null,"previous_names":["fpw/yamas"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/fpw/yamas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fpw%2Fyamas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fpw%2Fyamas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fpw%2Fyamas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fpw%2Fyamas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fpw","download_url":"https://codeload.github.com/fpw/yamas/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fpw%2Fyamas/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260340351,"owners_count":22994465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembler","pdp-8","retrocomputing","vintage-computers"],"created_at":"2024-09-24T23:00:09.481Z","updated_at":"2025-06-22T07:38:15.706Z","avatar_url":"https://github.com/fpw.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\r\nThis is Yamas – Yet Another Macro Assembler: A PAL-compatible assembler for PDP-8 computers. It also includes support\r\nmacros in the syntax of [MACRO-8 (PDF manual)]. It is a complete clean-room implementation of a PDP-8 assembler using web technologies so that\r\nthe assembler can be integrated into web applications, apps on phones and the like. Of course, it also comes with a traditional shell command (through Node.js).\r\n\r\n## Usage\r\nIf [Node.js](https://nodejs.org) is installed, it should be possible to just do `npx yamas \u003cfile.pa\u003e`. The core assembler has no dependencies to Node.js and can run right in the browser, demo page coming soon!\r\n\r\n# FAQs\r\n## Assembler FAQ\r\n### Why another assembler for the PDP-8?\r\nWhile [palbart] and [macro8x] exist, it would be hard to adapt them for usage on the web. For example, creating a proper\r\nsyntax highlighter requires knowledge about the abstract syntax tree (AST) of the program, something that the existing\r\nassemblers don't even have since they're traditional two-pass assemblers that directly emit output symbols while still\r\nparsing the input. Yamas is built more like a compiler than an assembler: it creates an AST using a parser and a lexer\r\nthat is then passed to the actual assembler with the possibility to access the artifacts created in between. This enables\r\ntools like code editors to access the AST to query defined symbols, expanded macros and the like.\r\n\r\n### Which pseudo symbols are supported?\r\nCurrently, the following pseudos are supported:\r\n\r\n Type | Pseudos\r\n------|---------\r\nControl of origin       |`PAGE`,    `FIELD`,    `RELOC`\r\nConditionals and macros |`IFDEF`,   `IFNDEF`,   `IFNZRO`,   `IFZERO`,   `DEFINE`\r\nData output             |`TEXT`,    `ZBLOCK`,   `DUBL`,     `FLTG`,     `DEVICE`,   `FILENAME`\r\nSymbol table control    |`EXPUNGE`, `FIXTAB`,   `FIXMRI`\r\nRadix control           |`DECIMAL`, `OCTAL`\r\nOutput control          |`NOPUNCH`, `ENPUNCH`\r\nNo-ops                  |`EJECT`,   `XLIST`,    `PAUSE`\r\n\r\n### Is the generated code correct?\r\n\"Correct\" is hard to define since there are many different dialects of the language that are treated\r\ndifferently by different assemblers. But the output should match the output of PAL8. Any mismatch is considered\r\na bug. Yamas currently passes the [palbart testbench], including the \"bad\" directory where palbart fails.\r\nIt also uses extensive unit tests so that new features don't break things that once worked.\r\n\r\n### Any deviations?\r\nThere are some known and accepted deviations:\r\n\r\n* parameter assignment (`A=B`) uses the PAL8 syntax and not the MACRO-8 syntax. This means that things like ``A=DECIMAL 10 OCTAL`` are not supported.\r\n* floating point literals are more accurate than the ones generated by PAL8.\r\n\r\n### But in my own tests, the generated bin files differ?\r\nWhat matters is the machine state after reading the bin files. It's okay if things have a different order on the bin tape.\r\nFor example, the literal table is output at a different time. Palbart does the same and the bin tapes don't match PAL8.\r\nThat's why comparisons of bin files should be done with a special tool like [cmp_tape]. Yamas also includes the `-c` option to compare its output with a given bin file, noting the differences in the resulting state.\r\n\r\n## Language FAQ\r\n### Why do both FIXMRI and FIXTAB exist when FIXTAB auto-detects MRIs?\r\nBecause some external hardware might use the data break to read memory and expect custom operations that act like MRIs.\r\nA prominent example is the external floating point unit: It introduces custom opcodes that it executes as a co-processor.\r\nSome of these custom opcodes need an MRI-like operand even though the opcode starts with 6 or 7. For example, the Focal code\r\ndefines ``FIXMRI FPT=6000`` which wouldn't work with the auto-detection of `FIXTAB`.\r\n\r\n### How are comments inside macros and conditional statements handled?\r\nThey are parsed as comments, but if they contain a '\u003e', it will still end the current macro body.\r\nInterestingly, the rest of the line after the closing '\u003e' is still handled as a comment, i.e. not parsed.\r\nExample: ``IFDEFA \u003cI/O ERROR\u003e`` is legal: it either assembles as `I` (value 0400) or not at all, depending on `A`.\r\nThis matches the behavior of PAL8.\r\n\r\n## Implementation FAQ\r\n### Why no parser generator?\r\nThis project was also a personal project for me to strengthen skills that I hardly need for my day job,\r\nsuch as writing lexers and parsers.\r\n\r\n### Why can expressions be null? Also, why not undefined?\r\nExpressions can be null in pass 1, for example when a symbol is used that is only defined later. This is okay unless the expression changes the CLC.\r\nFor that reason, the assembler differentiates between defined and undefined expressions. Using an undefined expression in an `IFZERO` is not okay\r\nbecause the resulting CLC can't be calculated - but using it in something like ``A=JMS X`` is completely fine.\r\n\r\n`null` is used instead of `define` so that the linter will spot a missing `case`\r\nin the eval functions after adding a new node type. It would probably be better to\r\nuse a `Maybe` type so that expressions like `if (!val)` are also caught.\r\n\r\n### Why does the origin operator always lead to origin symbols in the binary tape? Couldn't this be optimized to only write them when necessary?\r\nSome programs deliberately use the origin operator to generate RIM loader sections in the punched tape, e.g. TSS/8.\r\n\r\n### Why does the assembler emit callbacks instead of simply returning the target memory state and creating the bin tape from there?\r\nSee above: The origin statements must be preserved as they appeared in the code.\r\n\r\n[palbart]: http://www.pdp8online.com/ftp/software/palbart/\r\n[macro8x]: http://simh.trailing-edge.com/sources/simtools/crossassemblers/\r\n[palbart testbench]: http://www.pdp8online.com/ftp/software/palbart/testbench/\r\n[cmp_tape]: http://www.pdp8online.com/ftp/software/cmp_tape/\r\n[MACRO-8 (PDF manual)]: http://www.bitsavers.org/pdf/dec/pdp8/software/DEC-08-CMAB-D_MACRO8.pdf\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffpw%2Fyamas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffpw%2Fyamas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffpw%2Fyamas/lists"}