{"id":22933604,"url":"https://github.com/gustavodiasag/clox","last_synced_at":"2025-07-20T09:12:42.630Z","repository":{"id":171764947,"uuid":"648313668","full_name":"gustavodiasag/clox","owner":"gustavodiasag","description":"Virtual machine interpreter for the Lox programming language written in C","archived":false,"fork":false,"pushed_at":"2024-01-23T02:04:30.000Z","size":440,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-01T08:44:39.875Z","etag":null,"topics":["bytecode","c","compiler-design","garbage-collection","interpreter","programming-language","virtual-machine"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gustavodiasag.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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-06-01T17:23:05.000Z","updated_at":"2024-02-01T16:13:25.000Z","dependencies_parsed_at":"2023-10-14T22:16:11.067Z","dependency_job_id":"9c2e3338-5990-401b-9992-7086260f5596","html_url":"https://github.com/gustavodiasag/clox","commit_stats":null,"previous_names":["gustavodiasag/clox"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gustavodiasag/clox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavodiasag%2Fclox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavodiasag%2Fclox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavodiasag%2Fclox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavodiasag%2Fclox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gustavodiasag","download_url":"https://codeload.github.com/gustavodiasag/clox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavodiasag%2Fclox/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266094082,"owners_count":23875570,"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":["bytecode","c","compiler-design","garbage-collection","interpreter","programming-language","virtual-machine"],"created_at":"2024-12-14T11:32:20.564Z","updated_at":"2025-07-20T09:12:42.608Z","avatar_url":"https://github.com/gustavodiasag.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clox\n\nclox is a C99 implementation of a bytecode virtual machine interpreter for the [Lox programming language](https://www.craftinginterpreters.com/the-lox-language.html) following the third part of Robert Nystrom's [Crafting Interpreters](https://craftinginterpreters.com/).\n\nTwo versions of the interpreter are instructed by the author, the first one being written in Java, which uses an AST-based style of implementation. The main reason for writing another Lox interpreter using a different approach is that walking through an Abstract Syntax Tree is not [memory-efficient](http://gameprogrammingpatterns.com/data-locality.html), since each piece of syntax in the language becomes a heap-stored AST node. To avoid that, this implementation focuses on exploring and taking advantage of CPU caching by ways of representing code in memory in a denser and more ordered way.\n\n# Usage\n\n## Build\n\nThe project relies on [CMake](https://cmake.org/download/) (3.16.3+), which is strictly required in order to build it. After installation, simply clone the project and run: \n\n```sh\n$ mkdir build \u0026\u0026 cd build/    # CMake workspace.\n$ cmake .. \u0026\u0026 cmake --build .\n```\n\nA few customizable build settings can be set using CMake's `CACHE` entries:\n\n```\ncmake [-D \u003coption\u003e=1 ] ..\n```\n\nWhere options are non-exclusive and consist of:\n\n- `DEBUG`: logs the bytecode compiled and the runtime stack state during the execution of each instruction.\n\n- `LOG_GC`: triggers garbage collection more frequently, logging its [tracing](NOTES.md/#mark-sweep-garbage-collection) and the amount of memory reclaimed.\n\n- `OPTIMIZE`: changes clox's representation of values, switching from tagged unions to NaN-boxing.\n\n## Run\n\nLox programs can be interpreted as source files or through a REPL interface, by just omitting the file path. A few [example programs](examples/) are provided.\n\n```sh\n$ ./clox [filepath]\n```\n\n# Notes\n\nBesides the main purpose of the book, which is the actual implementation of the interpreters, a bunch of concepts and theorems regarding computer science as a whole is also presented throughout its content. Considering that some of this information, if not all of it, is crucial for one's path becoming a somewhat decent computer scientist, a whole [separate section](NOTES.md) is dedicated to it.\n\n# Lox\n\nIn a brief description, Lox is a high-level, dynamically typed, garbage-collected programming language that borrows ideas from functional, procedural and object-oriented programming to provide the flexibility expected of a simple scripting language.\n\nIt provides most of the functionalities from a basic language implementation, such as data types, expressions, statements, variables, control flow and functions. Besides that, features like classes and closures are also specified, whose complexity is deserving of a more thorough depiction.\n\n## Classes\n\nA class and its methods can be declared in Lox like so:\n\n```js\nclass Example {\n    foo() {\n        print \"Foo.\";\n    }\n\n    bar(baz) {\n        print \"This is \" + baz + \".\";\n    }\n}\n\nvar example = Example();\nprint example // \"Example instance\".\n```\n\nWhen the declaration is executed, Lox creates a class object and stores it in a variable named after the class, which turns it to a first-class value in the language. Classes in Lox are also factory functions for instances, producing them when called.\n\n### Instantiation\n\nClasses in Lox also hold state in the form of properties, which can be freely added onto objects. Assigning to a property creates it if it doesn't already exist.\n\n```js\nexample.foobar = \"foobar\";\nexample.qux = \"qux\";\n```\n\nThe keyword `this` is used to access a field or method on the class object from within a method.\n\n### Initialization\n\nIf a class has a method named `init()`, it is called automatically when the object is constructed.\n\n```js\nclass Example {\n    init(foobar, qux) {\n        this.foobar = foobar;\n        this.qux = qux;\n    }\n}\n\nvar example = Example(\"foobar\", \"qux\");\n```\n\n### Inheritance\n\nLox supports single inheritance. When a class is declared, its inheriting behaviour can be specified with `\u003c`. Every method defined in the superclass is also available to its subclasses, including `init()`.\n\n```js\nclass Text \u003c Example {\n    init(foobar, qux, quux) {\n        super.init(foobar, qux);\n        this.quux = quux;\n    }\n}\n```\n\n## Closures\n\nConsidering that functions are defined as first-class values in Lox and that function declarations are statements, the combination of those along with block scope can lead to a behaviour whose semantics are specified by **closures**.\n\n```js\nfun outer() {\n    var outside = \"outside\";\n\n    fun inner() {\n        print outside;\n    }\n\n    return inner;\n}\n\nvar fn = outer();\n// ...\nfn();\n```\n\nIn the above example, `inner()` must keep a reference to any surrounding variables that it uses so that they still exist after the outer function has returned. For that, the function [closes over](NOTES.md/#closure-implementation) the variables' [values](NOTES.md/#upvalues) at the moment of the call.\n\n## Grammar\n\nThe syntax rules in the [Extended Backus-Naur Form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form) (EBNF) notation for Lox are presented below.\n\n```ebnf\nprogram         = declaration * EOF ;\n\n(* Declarations. *)\n\ndeclaration     = class_decl | fun_decl | var_decl | statement ;\n\nclass_decl      = \"class\" IDENTIFIER ( \"\u003c\" IDENTIFIER ) ? \"{\" function * \"}\"\n\nfun_decl        = \"fun\" function ;\n\nvar_decl        = \"var\" IDENTIFIER ( \"=\" expression ) ? \";\" ;\n\n(* Statements. *)\n\nstatement       = expr_stmt\n                | for_stmt\n                | if_stmt\n                | print_stmt\n                | return_stmt\n                | while_stmt\n                | block\n                ;\n\nexpr_stmt       = expression \";\" ;\n\nfor_stmt        = \"for\" \"(\" ( var_decl | expr_stmt | \";\" )\n                    expression ? \";\"\n                    expression ? \")\" statement\n\nif_stmt         = \"if\" \"(\" expression \")\" statement (\"else\" statement) ? ;\n\nprint_stmt      = \"print\" expression \";\" ;\n\nreturn_stmt     = \"return\" expression ? \";\" ;\n\nwhle_stmt       = \"while\" \"(\" expression \")\" statement ;\n\nblock           = \"{\" declaration * \"}\" ;\n\n(* Expressions. *)\n\nexpression      = assignment ;\n\nassignment      = ( call \".\" ) ? IDENTIFIER \"=\" assignment | logic_or ;\n\nlogic_or        = logic_and ( \"or\" logic_and ) * ;\n\nlogic_and       = equality ( \"and\" equality) * ;\n\nequality        = comparison ( ( \"!=\" | \"==\" ) comparison ) * ;\n\ncomparison      = term ( ( \"\u003e\" | \"\u003e=\" | \"\u003c\" | \"\u003c=\" ) term ) * ;\n\nterm            = factor ( ( \"-\" | \"+\" ) factor ) * ;\n\nfactor          = unary ( ( \"/\" | \"*\" ) unary ) * ;\n\nunary           = ( \"!\" | \"-\" ) unary | call ;\n\ncall            = primary ( \"(\" arguments ? \")\" | \".\" IDENTIFIER ) * ;\n\nprimary         = \"true\"\n                | \"false\"\n                | \"nil\"\n                | \"this\"\n                | NUMBER\n                | STRING\n                | IDENTIFIER\n                | \"(\" expression \")\"\n                | \"super\" \".\" IDENTIFIER\n                ;\n\n(* Utility rules. *)\n\nfunction        = IDENTIFIER \"(\" parameters ? \")\" block ;\n\nparameters      = IDENTIFIER ( \",\" IDENTIFIER ) * ;\n\narguments       = expression ( \",\" expression ) * ;\n\n(* Lexical grammar. *)\n\nNUMBER          = DIGIT + ( \".\" DIGIT ) ? ;\n\nSTRING          = '\"' ( ? all characters ? - '\"' ) * '\"' ;\n\nIDENTIFIER      = ALPHA ( ALPHA | DIGIT ) * ;\n\nALPHA           = \"a\" ... \"z\" | \"A\" ... \"Z\" | \"_\" ;\n\nDIGIT           = \"0\" ... \"9\" ;\n```\n\n# License\n\nThis project is licensed under the [MIT License](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavodiasag%2Fclox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgustavodiasag%2Fclox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavodiasag%2Fclox/lists"}