{"id":49052376,"url":"https://github.com/figgleforth/ore-lang","last_synced_at":"2026-04-19T21:12:11.951Z","repository":{"id":246906728,"uuid":"805982551","full_name":"figgleforth/ore-lang","owner":"figgleforth","description":"A programming language for web development, for fun","archived":false,"fork":false,"pushed_at":"2026-04-07T23:14:22.000Z","size":1324,"stargazers_count":7,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-08T01:19:36.315Z","etag":null,"topics":["programming","programming-language","programming-languages","ruby"],"latest_commit_sha":null,"homepage":"https://ore-docs.fly.dev","language":"Ruby","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/figgleforth.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-26T03:08:21.000Z","updated_at":"2026-04-07T23:14:31.000Z","dependencies_parsed_at":"2024-07-11T21:47:10.587Z","dependency_job_id":"3ac49f9c-8305-49fb-8f4f-8a937fdb2cc0","html_url":"https://github.com/figgleforth/ore-lang","commit_stats":null,"previous_names":["figgleforth/em","figgleforth/emerald","1987s/em","figgleforth/programming-language","figgleforth/ore-lang"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/figgleforth/ore-lang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figgleforth%2Fore-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figgleforth%2Fore-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figgleforth%2Fore-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figgleforth%2Fore-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/figgleforth","download_url":"https://codeload.github.com/figgleforth/ore-lang/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figgleforth%2Fore-lang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32022749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["programming","programming-language","programming-languages","ruby"],"created_at":"2026-04-19T21:12:09.335Z","updated_at":"2026-04-19T21:12:11.932Z","avatar_url":"https://github.com/figgleforth.png","language":"Ruby","readme":"![Version](https://img.shields.io/badge/version-0.0.0-2B7FFF.svg)\n![License: MIT](https://img.shields.io/badge/License-MIT-2B7FFF.svg)\n[![justforfunnoreally.dev badge](https://img.shields.io/badge/justforfunnoreally-dev-2B7FFF)](https://justforfunnoreally.dev)\n![Status of project Ruby tests](https://github.com/figgleforth/ore-lang/actions/workflows/tests.yml/badge.svg)\n\n### Quick Start\n\n\u003e Requires Ruby `3.4.1` or higher, and Bundler\n\n```bash\ngit clone https://github.com/figgleforth/ore-lang.git\ncd ore-lang\nbundle install\nbundle exec bin/ore examples/hello.ore # =\u003e Hello, Ore!\n```\n\nExample code from [examples/hello.ore](./examples/hello.ore):\n\n```ore\nGreet {\n\tsubject,\n\n\tnew { subject;\n\t\t.subject = subject\n\t}\n\n\tgreeting {;\n\t\t\"Hello, `subject`!\"\n\t}\n}\n\nGreet('Ore').greeting()\n```\n\n### Table of Contents\n\n- [Features](#features)\n- [Code Examples](#code-examples)\n\t- [Manual Type Contracts](#manual-type-contracts)\n\t- [Runtime Type Contracts](#runtime-type-contracts)\n\t- [Variables](#variables)\n\t- [Functions](#functions)\n\t- [Classes](#classes)\n\t- [Loops](#loops)\n\t- [Instance Unpacking](#instance-unpacking)\n\t- [File Loading](#file-loading)\n\t- [Database \u0026 ORM](#database--orm)\n\t- [Web Servers](#web-servers)\n\t- [HTML Rendering](#html-rendering)\n- [Project Structure](#project-structure)\n\n### Features\n\n- Gradual typing — opt in as needed\n\t- Static type checking at parse time for literal mismatches (`x: String = 99`)\n\t- Call site argument types checked against typed function signatures (`add(123, 'boo')`, `add { a: Number, b: NUmber }`)\n\t- Runtime type contracts via `:=` where type is inferred and enforced on future assignments (`x := 123`)\n\t- Plain `=` behaves dynamic without reassignment restrictions\n- Naming conventions replace keywords\n\t- `Capitalize` classes\n\t- `lowercase` variables and functions\n\t- `UPPERCASE` constants\n- Class composition replaces inheritance\n\t- `|` Union - merge classes (left side wins conflicts)\n\t- `\u0026` Intersection - keep only shared declarations\n\t- `~` Difference - discard right side declarations\n\t- `^` Symmetric Difference - discard shared declarations\n- Scope operators for explicit access\n\t- `.identifier` accesses instance scope only, like `self.identifier`\n\t- `./identifier` accesses type/static scope, like `self.class.identifier`\n\t- `../identifier` accesses global scope\n- First-class functions and classes\n- Data containers `Array`, `Tuple`, `Dictionary`\n- Loops like `for`, `while`, and `until`\n\t- Automatic `it` declaration for iteration value\n\t- Automatic `at` declaration for iteration index\n\t- `skip` and `stop` keywords for loop control\n\t- Stride support with `for x by 2` syntax\n- Unpacking an instance's declarations with `@` operator\n\t- Makes declarations accessible without `instance.` prefix\n\t- Auto-unpack function parameters in function body `funk { @with; }`\n\t- Manually unpack `@ += instance` and undo `@ -= instance`\n- Basic web server with routing\n\t- Route definitions use `method://path` syntax (e.g., `get://`, `post://users/:id`)\n\t- URL parameters via `:param` syntax\n\t- Query string and form data access via `request.query` and `request.body`\n\t- HTTP redirects with `response.redirect(url)`\n\t- Non-blocking `@start` directive allows running multiple servers\n\t- Graceful shutdown handling when program exits\n- Database ORM with SQLite\n\t- Base composable `Record` type with `all()`, `find()`, `create()`, `delete()` methods\n\t- Database operations via `Database` type\n\t- Schema definition with dictionaries\n\t- Static database linking with `./database = ../db`\n- HTML rendering with `Dom` composition\n\t- Compose HTML with built-in HTML DOM elements (`Dom`, `Html`, `Body`, `Div`, `H1`, etc)\n\t- Declare `html_` prefixed attributes for HTML attributes (`html_href`, `html_class`)\n\t- Declare `css_` prefixed properties for CSS (`css_color`, `css_background`)\n\t- Routes returning `Dom` instances automatically render to HTML\n\t- Standard library provides common HTML elements\n\n### Code Examples\n\n#### Manual Type Contracts\n\nManual Type Contracts are created by using `: Type` syntax on variables and function parameters.\n\n```ore\n# Variable annotations\nx: String = 'hello'   # ok\ny: Number = 42        # ok\nz: String = 99        # Type_Checking_Failed — String expected, Number given\n\n# Parameter annotations\nadd { a: Number, b: Number;\n\ta + b\n}\n\nadd(1, 2)      # ok\nadd(1, 'two')  # Type_Checking_Failed — Number expected for b, String given\n```\n\nAnnotations on variables whose values aren't known statically (e.g. the result of a function call or another identifier) are not checked at parse time — only literal mismatches are caught.\n\n#### Runtime Type Contracts\n\n`:=` infers a type from the right hand side and locks the variable to that type for future `=` assignments. Plain `=` without a prior `:=` or annotation stays fully dynamic.\n\n```ore\nx := 4        # x is now a Number\nx = 8         # ok — same type\nx = 'hello'   # Type_Contract_Violation — Number expected, got String\n\nx := 'hello'  # re-initialize — x is now a String\nx = 'world'   # ok\n\ny = 4\ny = 'hello'   # ok — no contract, fully dynamic\n```\n\n#### Variables\n\n```\n# Comments start with a hash\n\nnothing,            # Syntactic sugar for \"nothing = nil\"\nsomething = true\nokay_too = 42,      # Comma allowed as expression separator\n\n# Strings can be single or double quoted, and interpolated with backticks\nLANG_NAME = \"ore-lang\"\nversion   = '0.0.0'\nlines     = 4_815\nheader    = \"`LANG_NAME` v`version`\"   # \"ore-lang v0.0.0\"\nfooter    = 'Lines of code: `lines`'   # \"Lines of code: 4815\"\n\n# Ranges\ninclusive_range   = 0..2\nexclusive_range   = 2\u003e\u003c5\nl_exclusive_range = 5\u003e.7\nr_exclusive_range = 7.\u003c9\n\n# Data containers\ntuples = (header, footer)\narrays = [inclusive_range, exclusive_range]\n\n# Dictionaries can be initialized in multiple ways, commas and values are optional\ndict = {}                       # {}\ndict = {x y}                    # {x: nil, y: nil}\ndict = {u, v}                   # {u: nil, v: nil}\ndict = { a:0 b=1 c}             # {a: 0, b: 1, c: nil}\ndict = { x:4, y=8, z}           # {x: 4, y: 8, z: nil}\ndict = { v=version, l=lines }   # {v: \"0.0.0\", l: 4815}\n```\n\n#### Functions\n\n```\n# Syntax: \u003cfunction_name\u003e { \u003cparams, etc\u003e; \u003cbody\u003e }, where \";\" is the delimiter between params and body.\n\nnoop_function {;}\n\nbest_show {;\n\t\"Lost\"  # Last expression is return value\n}\n\nfizz_buzz { n;\n\tif n % 3 == 0 and n % 5 == 0\n\t\t'FizzBuzz'\n\telif n % 3 == 0\n\t\t'Fizz'\n\telif n % 5 == 0\n\t\t'Buzz'\n\telse\n\t\t'`n`'\n\tend           # Control flows close with `end`\n}                 # Code blocks close with `}`\n```\n\n#### Classes\n\n```\n# Syntax: \u003cclass_name\u003e { \u003cbody\u003e }\n\nRepo {\n\tuser,\n\tname,\n\n\t# \"new\" is reserved for constructors\n\tnew { user, name;\n\t\t.user = user\n\t\t.name = name\n\t}\n\n\tto_s {;\n\t\t\"`user`/`name`\"\n\t}\n}\n\nRepo('figgleforth', 'ore-lang').to_s() # \"figgleforth/ore-lang\"\n```\n\n#### Loops\n\n```ore\n# For loops iterate over arrays, ranges, and other iterables\nresult = []\nfor [1, 2, 3, 4, 5]\n\tresult \u003c\u003c it  # it is the current iteration value\nend\n# result = [1, 2, 3, 4, 5]\n\n# Map, select, reject, etc...\nfor [1, 2, 3] map\n\tit * 2\nend\n\n# Stride support with \"by\" keyword\nfor [1, 2, 3, 4] select by 2\n\tit # [1, 2] or [2, 4]\nend\n\nfor [1, 2, 3, 4] reject by 2,1 # the overlap amount\n\tit # [1, 2] or [2, 3] or [3,4]\nend\n\nfor [1, 2, 3, 4, 5, 6, 7] each by 3,1\n\tit # [1,2,3] or [3,4,5] or [5,6,7] ...\nend\n\nfor [1, 2, 3, 4, 5, 6, 7, 8] each by 4,2\n\tit # [1,2,3,4] or [3,4,5,6] or [5,6,7,8] ...\nend\n\n# Ranges work too\nsum = 0\nfor 1..10\n\tsum += it\nend\n# sum = 55\n\n# Access iteration index with `at`\nindexed = []\nfor ['a', 'b', 'c']\n\tindexed \u003c\u003c \"`at`: `it`\"\nend\n# indexed = [\"0: a\", \"1: b\", \"2: c\"]\n\n# Loop control with skip and stop\nevens = []\nfor 1..10\n\tif it % 2 != 0\n\t\tskip  # Continue to next iteration\n\tend\n\tevens \u003c\u003c it\n\tif it == 6\n\t\tstop  # Break out of loop\n\tend\nend\n# evens = [2, 4, 6]\n```\n\n#### Instance Unpacking\n\n```ore\nVector {\n\tx,\n\ty,\n\n\tnew { x, y;\n\t\t.x = x\n\t\t.y = y\n\t}\n}\n\n# Auto-unpack in function parameters with @\nadd { @vec;\n\tx + y  # Access vec.x and vec.y directly without vec. prefix\n}\n\nv = Vector(3, 4)\nadd(v)  # 7\n\n# Manual sibling scope control\nmultiply { factor;\n\tv1 = Vector(5, 10)\n\t@ += v1  # Add v1's members to sibling scope\n\n\tresult_x = x * factor  # Access x directly\n\tresult_y = y * factor  # Access y directly\n\n\t@ -= v1  # Remove v1 from sibling scope\n\n\tVector(result_x, result_y)\n}\n\nmultiply(2)  # Vector(10, 20)\n```\n\n#### File Loading\n\n```ore\n# Load external Ore files with @use directive\n@use './some_formatter.ore'\n@use './some_dir/users.ore'\n\n# Use loaded classes and functions\nuser = User('Alice', 'alice@example.com')\nformatted = format_name(user.name)\n```\n\n#### Database \u0026 ORM\n\n```ore\n@use 'ore/database.ore'\n@use 'ore/record.ore'\n\n# Create and connect to database\ndb = Sqlite('./temp/blog.db')\n@connect db\n\n# Create table with schema\ndb.create_table('posts', {\n\tid: 'primary_key',\n\ttitle: 'String',\n\tbody: 'String'\n})\n\n# Define model by composing with Record\nPost | Record {\n\t./database = ../db     # Link to static ..database declaration\n\ttable_name = 'posts'\n}\n\n# Create records\nPost.create({title: \"Hello Ore\", body: \"Building web apps is fun!\"})\nPost.create({title: \"Databases\", body: \"SQLite integration works!\"})\n\n# Query records\nposts = Post.all()         # Fetch all posts\npost = Post.find(1)        # Find by ID\n\n# Access record data (returns Dictionary)\npost[:title]               # \"Hello Ore\"\npost[:body]                # \"Building web apps is fun!\"\n\n# Delete records\nPost.delete(2)\n```\n\n\u003e For a complete full-stack example, see [todo_app.ore](examples/todo_app.ore) which combines Database, ORM, Server, HTML rendering, and forms into a working CRUD application.\n\n#### Web Servers\n\n```ore\n@use 'ore/server.ore'\n\n# Create servers by composing with built-in Server type\nWeb_App | Server {\n\t# Define routes using HTTP method and path\n\tget:// {;\n\t\t\"\u003ch1\u003eWelcome to Ore!\u003c/h1\u003e\"\n\t}\n\n\tget://hello/:name { name;\n\t\t\"\u003ch1\u003eHello, `name`!\u003c/h1\u003e\"\n\t}\n\n\tpost://submit {;\n\t\t\"Form submitted\"\n\t}\n}\n\nAPI_Server | Server {\n\tget://api/users {;\n\t\t\"[{\\\"id\\\": 1, \\\"name\\\": \\\"Alice\\\"}]\"\n\t}\n}\n\n# Both servers run concurrently in background threads\napp = Web_App(8080)\napi = API_Server(3000)\n@start app\n@start api\n```\n\n#### HTML Rendering\n\nUsing built-in `Dom` composition:\n\n```ore\n@use 'ore/html.ore'\n\nLayout | Dom {\n\ttitle,\n\tbody_content,\n\n\tnew { title = 'My page', body_content = 'Hello!';\n\t\t.title = title\n\t\t.body_content = body_content\n\t}\n\n\trender {;\n\t\t# Use built-in Html, Head, Title, and Body types\n\t\tHtml([\n\t\t\tHead(Title(title)),\n\t\t\tBody(body_content)\n\t\t])\n\t}\n}\n```\n\nUsing strings with HTML:\n\n```ore\n@use 'ore/html.ore'\n\nLayout | Dom {\n\trender {;\n\t\t\"\u003chtml\u003e\u003chead\u003e\u003ctitle\u003eMy page\u003c/title\u003e\u003c/head\u003e\u003cbody\u003eHello!\u003c/body\u003e\u003c/html\u003e\"\n\t}\n}\n```\n\nBoth examples will produce an HTML response as long as the class composes with `Dom`:\n\n```\n\u003chtml\u003e\n\t\u003chead\u003e\n\t\t\u003ctitle\u003eMy page\u003c/title\u003e\n\t\u003c/head\u003e\n\t\u003cbody\u003e\n\t\tHello!\n\t\u003c/body\u003e\n\u003c/html\u003e\n```\n\nAdding HTML and CSS attributes:\n\n```ore\n@use 'ore/html.ore'\n\nMy_Div | Dom {\n\thtml_element = 'p'\n\thtml_class = 'my_class'\n\thtml_id = 'my_id'\n\tcss_background_color = 'black'\n\tcss_color = 'white'\n}\n\n# =\u003e \u003cp class='my_class' id='my_id' style='background-color:black;color:white;'\u003e\u003c/p\u003e\n```\n\nNote: Rendering HTML only works when `render{;}` is called by a Server instance. See [html.ore](ore/html.ore) for predefined `Dom` elements. See [web1.ore](examples/web1.ore) for Server and HTML usage.\n\n### Project Structure\n\n- [`src/readme`](src/readme.md) details the architecture and contains instructions for running your own programs\n- [`examples`](examples) contains code examples written in Ore\n- [`ore`](ore) contains code for the Ore standard library\n- [`src`](src) contains code implementing Ore\n    - [Lexer](src/compiler/lexer.rb) – Source code to Lexemes\n    - [Parser](src/compiler/parser.rb) – Lexemes to Expressions\n    - [Type_Checker](src/compiler/type_checker.rb) – Basic type annotation checking\n    - [Interpreter](src/runtime/interpreter.rb) – Entry point; `run(source)` lexes, parses, and executes\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiggleforth%2Fore-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffiggleforth%2Fore-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiggleforth%2Fore-lang/lists"}