{"id":13822150,"url":"https://github.com/jamiebuilds/ghost-lang","last_synced_at":"2026-01-25T06:45:17.817Z","repository":{"id":66094874,"uuid":"155635165","full_name":"jamiebuilds/ghost-lang","owner":"jamiebuilds","description":":ghost: A friendly little language for you and me.","archived":false,"fork":false,"pushed_at":"2024-04-06T00:10:35.000Z","size":45,"stargazers_count":303,"open_issues_count":15,"forks_count":10,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-12T21:02:43.587Z","etag":null,"topics":["programming-language","spec"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamiebuilds.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-10-31T23:17:55.000Z","updated_at":"2025-02-25T05:19:28.000Z","dependencies_parsed_at":"2024-08-04T08:07:53.478Z","dependency_job_id":"49850b26-04f8-4d5a-93c7-ea8a4a83bbac","html_url":"https://github.com/jamiebuilds/ghost-lang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamiebuilds%2Fghost-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamiebuilds%2Fghost-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamiebuilds%2Fghost-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamiebuilds%2Fghost-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamiebuilds","download_url":"https://codeload.github.com/jamiebuilds/ghost-lang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246651561,"owners_count":20811994,"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":["programming-language","spec"],"created_at":"2024-08-04T08:01:45.227Z","updated_at":"2026-01-25T06:45:17.788Z","avatar_url":"https://github.com/jamiebuilds.png","language":null,"funding_links":[],"categories":["Others"],"sub_categories":[],"readme":"# Ghost Lang 👻\n\nA friendly little language for you and me.\n\n## Motivation\n\nGhost is the language I wish we had.\n\nThere are so many newer programming languages that have brilliant ideas inside\nthem, but I think they have failed to make them _feel_ familiar to programmers.\n\nGhost steals as much of its design as possible from other programming\nlanguages. If someone else did it really well, why do it any differently? As\nsuch most of Ghost won't _feel_ new. If you've used some of these languages\nbefore you will probably recognize features of Ghost.\n\nThere is no compiler or any tools for Ghost right now, I hope to someday work\non some. But for now, this is just an exercise in programming language design.\n\n## Syntax\n\nGhost's syntax should feel light. There are no semicons, comments are a single\ncharacter (`#`), syntax avoid too many characters.\n\nBut it also avoids having \"optional\" syntax like optional parenthesis or curly\nbraces. A lot of this encourages a more \"vertical\" coding style.\n\nPlaces where syntax could go multiple different ways, I've just picked what\nseems to be most popular. That way it should feel familiar to lots of\ndevelopers.\n\n### Comments\n\n```coffee\n# inline comments only\n# combine to make multiline\n```\n\n### Variables\n\n```coffee\nlet name = expression\n```\n\n### Booleans\n\n```coffee\nlet positive = true\nlet negative = false\n```\n\n### Strings\n\n```coffee\nlet plain = \"hello world\"\nlet interpolated = \"hello {target}\"\nlet escapes = \"hello \\\"world\\\"\"\n\nlet multiline =\n  \"\"\"\n  The quick {color} fox           # comment\n  {action} over the lazy dog     \\# not comment\n  \"\"\"\nlet multilineWithNewlines =\n  \"\"\"\n  This is the first line\n  This is the second line\\\n  This is still the second line\n  \"\"\"\nlet multilineWithIndentation =\n  \"\"\"\n  This is indented by 0 spaces.\n    This is indented by 2 spaces.\n      This is indented by 4 spaces.\n  \"\"\"\n```\n\n### Integers\n\n```coffee\nlet integer = 42\nlet negative = -42\nlet hex = 0x2A\nlet octal = 0o52\nlet binary = 0b101010\nlet separators = 42_000 # may only be between any two digits\nlet byte = b'a' # u8 only\n```\n\n### Floats\n\n```coffee\nlet float = 4.2 # `.` must be between digits (ex: 0.42 or 42.0)\nlet negative = -4.2\nlet separators = 4_000.000_002 # may only be between any two digits\n```\n\n### Regex\n\n```coffee\nlet regex = /^one|^two|^three|^orfour/i # equivalent to below\nlet regexMultiline = ///\n  ^ one   |  # all whitespace\n  ^ two   |  # and comments\n  ^ three |  # will be ignored\n  ^ or four  # to make it readable\n///i\n```\n\n### Structs\n\n```coffee\nstruct Rect {\n  x: Int32\n  y: Int32\n  width: Int32\n  height: Int32\n}\n\nlet rect = Rect {\n  x: 10,\n  y: 20,\n  width: 1\n}\n```\n\n### Enums\n\n```coffee\nenum Action {\n  Reset()\n  Increment(amount: Int32 = 1)\n  Decrement(amount: Int32 = 1)\n}\n\nlet reset = Action.Reset()\nlet increment = Action.Increment()\nlet increment2 = Action.Increment(2)\nlet decrement3 = Action.Decrement(amount: 3)\n```\n\n### Operators\n\n```coffee\n# Arithmetic\nlet addition = a + b\nlet subtraction = a - b\nlet division = a / b\nlet multiplication = a * b\nlet remainder = a % b\nlet exponentiation = a ** b\nlet negation = -a\n\n# Comparison\nlet equality = a == b\nlet referentialEquality = a === b\n\nlet lessThan = a \u003c b\nlet lessThan2 = a \u003c b \u003c c # equivalent to `a \u003c b \u0026\u0026 b \u003c c`, except `b` is only evaluated once\nlet lte = a \u003c= b\nlet lte2 = a \u003c= b \u003c= c\nlet lessThan3 = a \u003c= b \u003c c\n\nlet greaterThan = a \u003e b\nlet greaterThan2 = a \u003e b \u003e c\nlet gte = a \u003e= b\nlet gte2 = a \u003e= b \u003e= c\nlet greaterThan3 = a \u003e= b \u003e c\n\n# Logical\nlet and = expr \u0026\u0026 expr\nlet or = expr || expr\nlet not = !expr\n\n# Grouping\nlet either = (a \u0026\u0026 b) || (c \u0026\u0026 d)\n```\n\n### If-Else\n\n```js\nif condition {\n  doSomethingIfTruthy()\n}\n\nif condition {\n  doSomethingIfTruthy()\n} else {\n  doSomethingElse()\n}\n\nif condition {\n  doSomethingIfTruthy()\n} else if condition2 {\n  doSomethingElseIf2Truthy()\n} else {\n  doSomethingElse()\n}\n\nlet result = if n == 0 {\n  \"none\"\n} else if n == 1 {\n  \"one\"\n} else {\n  \"many\"\n}\n```\n\n### Is\n\n```coffee\nif value is Action.Reset {}\nif value is Action.Increment(value) { value }\nif value is Action.Decrement(amount: value) { value }\n```\n\n### Match\n\n```coffee\nlet result = match value {\n  is true { \"true\" }\n  is false { \"false\" }\n  else { \"other\" }\n}\n```\n\n### For-As\n\n```coffee\nfor iterable as item {\n  if shouldBeSkipped(item) { continue }\n  if shouldEndTheLoop(item) { break }\n  doSomething()\n}\n```\n\n### While\n\n```coffee\nwhile condition {\n  onlyRunsIfConditionIsTrue()\n  repeatsAsLongAsItRemainsTrue()\n}\n```\n\n### Loop\n\n```coffee\nloop {\n  if condition1 { break }\n  if condition2 { continue }\n  doSomethingInfinitelyUntilBreak()\n}\n```\n\n### Functions\n\n```coffee\nfn add(a: Int32, b: Int32) {\n  a + b\n}\nfn subtract(a: Int32, b: Int32) {\n  let minuend = a\n  let subtrahend = b\n  minuend - subtrahend\n}\n\nlet result = add(400, subtract(42, 22))\n```\n\n### Named Params\n\n```coffee\nfn divide(dividend: Int32, divisor: Int32) {\n  dividend / divisor\n}\n\n# All of these are equivalent:\ndivide(400, 20)\ndivide(dividend: 400, divisor: 20)\ndivide(divisor: 20, dividend: 400)\ndivide(dividend: 400, 20)\ndivide(400, divisor: 20)\ndivide(divisor: 20, 400)\n\n# Compiler Errors: Cannot pass multiple values to the same parameter\ndivide(dividend: 20, dividend: 400)\ndivide(20, dividend: 400)\n```\n\n### Iterable Functions\n\n```coffee\nfn doubles(iter): Iter\u003cInt32\u003e {\n  for iter as value {\n    yield value * 2\n  }\n}\n\nfn invalid() {\n  yield 42 # Error\n}\n```\n\n### Blocks\n\n```coffee\nlet value = {\n  let a = 42\n  let b = 10\n  a * b\n}\n```\n\n### Pipeline\n\n```coffee\nlet results =\n  | books\n  | Iter.filter(^^, fn (book) {\n      book.popularity \u003e 0.8\n    })\n  | Iter.map(^^, fn (book) { Http.request(.get, book.url) })\n\n# Equivalent code without pipelines:\nlet filtered = Iter.filter(books, fn (book) { book.popularity \u003e 0.8 })\nlet results = Iter.map(filtered, fn (book) { Http.request(.get, book.url) })\n```\n\n### Junk\n\n```coffee\nlet _ = \"ignore me\"\nlet [_, _, three] = [1, 2, 3]\nlet {a as _, b as _, ...rest as _} = { a = 1, b = 2, c = 3, d = 4 }\n\ndoSomething(fn (_, _, value) {\n  value\n})\n\nlog(_)\n# SyntaxError: \"Junk\" bindings (_) are not valid\n# identifiers and cannot be referenced. Give your\n# binding a name instead.\n```\n\n### Elements (GSX)\n\n```coffee\nlet view = OtherComponent(prop, bar: true) {\n  let target = \"world\"\n  Text(\"hello {target}\")\n  List {\n    for items as item {\n      Text(item.name)\n    }\n  }\n}\n```\n\n### Use\n\n```coffee\nuse std/time\n```\n\n### Pub\n\n```coffee\npub let add = fn (a, b) { a + b }\npub let PI = 3.14\n```\n\n## Type Syntax\n\n### Type Alias\n\n```coffee\ntype MyType = Bool\n```\n\n### Primitive Types\n\n```coffee\ntype T = Empty\ntype T = Never\n\ntype T = Boolean\n\ntype T = Int8\ntype T = Int16\ntype T = Int32\ntype T = Int64\ntype T = Int128\ntype T = IntSize\n\ntype T = Uint8\ntype T = Uint16\ntype T = Uint32\ntype T = Uint64\ntype T = Uint128\ntype T = USize\n\ntype T = Float32\ntype T = Float64\n```\n\n### Maybe Types\n\n```coffee\ntype T = Maybe\u003cBoolean\u003e\n```\n\n### Result Types\n\n```coffee\ntype T = Result\u003cBoolean\u003e\n```\n\n### Function Types\n\n```coffee\ntype T = fn (param: String): USize\ntype T = fn (param: String): Iter\u003cUSize\u003e \n```\n\n### Generic Types\n\n```coffee\ntype T\u003cT\u003e = Option\u003cT\u003e\ntype T = fn \u003cT\u003e(param: T): T\n```\n\n### Unions\n\n```coffee\ntype MyType = Int8 | Int16 | Int32\ntype MyType =\n  | Int8\n  | Int16\n  | Int32\n```\n\n## Types in Syntax\n\n### Variables\n\n```coffee\nlet value: Boolean = true\nlet value: Boolean | String = \"cool\"\n```\n\n### Functions\n\n```coffee\nlet fn = fn (param1: String, param2: Number) {\n  # ...\n}\n\nlet fn = fn (...rest: Array\u003cString\u003e) {\n  # ...\n}\n\nlet fn = fn (): String {\n  \"nice\"\n}\n\nlet fn = fn (): Iter\u003cString\u003e iter {\n  yield \"good\"\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamiebuilds%2Fghost-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamiebuilds%2Fghost-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamiebuilds%2Fghost-lang/lists"}