{"id":37195698,"url":"https://github.com/mochatek/frolang","last_synced_at":"2026-01-14T22:45:13.640Z","repository":{"id":62099207,"uuid":"555400390","full_name":"mochatek/frolang","owner":"mochatek","description":"🐸FroLang: An interpreted toy language written in Go","archived":false,"fork":false,"pushed_at":"2022-11-04T07:51:30.000Z","size":268,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-20T22:33:29.594Z","etag":null,"topics":["frolang","golang","interpreter","programming-language"],"latest_commit_sha":null,"homepage":"","language":"Go","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/mochatek.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}},"created_at":"2022-10-21T14:00:09.000Z","updated_at":"2024-06-20T22:33:29.595Z","dependencies_parsed_at":"2022-10-26T11:15:59.352Z","dependency_job_id":null,"html_url":"https://github.com/mochatek/frolang","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mochatek/frolang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochatek%2Ffrolang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochatek%2Ffrolang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochatek%2Ffrolang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochatek%2Ffrolang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mochatek","download_url":"https://codeload.github.com/mochatek/frolang/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochatek%2Ffrolang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28436783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["frolang","golang","interpreter","programming-language"],"created_at":"2026-01-14T22:45:12.910Z","updated_at":"2026-01-14T22:45:13.603Z","avatar_url":"https://github.com/mochatek.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🐸 FroLang v0.1.0\nFroLang is an interpreted, interactive, dynamic typed, open-source toy programming language created for the sole purpose of learning how to build an interpreter and to sharpen my Go skills.\n\nFroLang is purely written in Go, with a syntax that is a hybrid of Python and JS. It contains all the basic features in any programming language along with a wide range of built-in methods for general use. FroLang is portable: it runs on many Unix variants, on the Mac, and on Windows 2000 and later.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/mochatek/frolang/blob/master/logo.svg\" alt=\"Logo\" /\u003e\n\u003c/p\u003e\n\n__How does it work?__\n\nFroLang interpreter uses an approach called _Tree-Walking_, which parses the source code, builds an abstract syntax tree (AST), and then evaluates this tree. These are the steps involved:\n\n1. __Lexical Analysis__: from source code (free text) to Tokens/Lexemes;\n2. __Parsing__: uses the generated tokens to create an Abstract Syntax Tree;\n3. __AST Construction__: a structural representation of the source code with its precedence level, associativity, etc;\n4. __Evaluation__: runs through the AST evaluating all expressions.\n\n## Installation and Usage\nYou can follow any of these methods to install and use FroLang:\n\n1. Running from source code:\n    - Clone this repo\n    - Install [Go](https://go.dev/dl/)\n    - Run `go run main.go` for the _REPL_\n    - Run `go run main.go fro_script_path` to run a valid _.fro_ script\n2. If Go is already installed in the system, then:\n    - Install frolang: `go install github.com/mochatek/frolang`\n    - Run `frolang` for the _REPL_\n    - Run `frolang fro_script_path` to run a valid _.fro_ script\n3. Docker: [FroLang Image](https://hub.docker.com/r/mochatek/frolang)\n4. Download the compiled binary from [Releases](https://github.com/mochatek/frolang/releases)\n    - Add the binary to PATH if you want to use FroLang from any location\n\n# Features\n- [Variables](#variables)\n- [Comments](#comments)\n- [Primitive Data Types](#primitive-data-types)\n  - [Integer](#integer)\n  - [Float](#float)\n  - [String](#string)\n  - [Boolean](#boolean)\n- [Container Types](#container-types)\n  - [Array](#array)\n  - [Hash](#hash)\n- [Functions](#functions)\n- [Operators](#operators)\n  - [Arithmetic operators](#arithmetic-operators)\n  - [String operators](#string-operators)\n  - [Conditional operators](#conditional-operators)\n  - [Logical operators](#logical-operators)\n  - [Presence operators](#presence-operators)\n- [Conditionals](#conditionals)\n- [Loops](#loops)\n    - [For in Loop](#for-in-loop)\n    - [While Loop](#while-loop)\n- [Jump Statements](#jump-statements)\n- [Error Handling](#error-handling)\n- [Builtin Methods](#builtin-methods)\n- [To-Do](#to-do)\n\n## Variables\n- Declare variables using `let` keyword\n- Variable name should only contain letters and underscore\n- Variable names are case sensitive\n- Variables in FroLang are __block scoped__\n\n**Example**\n```js\nlet language_name = \"FroLang\";\n```\n\n## Comments\nIn FroLang, you can create single/multi-line comment using `/* */`\n\n**Example**\n```js\n/* This is a comment */\n```\n\n## Primitive Data Types\nFollowing primitive types are available in FroLang:\n\n### Integer\n- Whole-valued positive, negative number or zero\n- Truthy value: Non zero value\n\n**Example**\n```js\nlet rank = 1;\n```\n\n### Float\n- Positive or negative whole number with a decimal point\n- Truthy value: Non zero value\n\n**Example**\n```js\nlet version = 1.1;\n```\n\n### String\n- Sequence of characters enclosed in double quotes\n- You can access individual character by their index and index starts from 0\n- Strings in FroLang are immutable\n- Truthy value: Non empty string\n\n**Example**\n```js\nlet author = \"MochaTek\";\nlet firstCharacter = author[0];\n```\n\n### Boolean\n- Represents truth value; ie, true / false\n- Truthy value: true\n\n**Example**\n```js\nlet completed = false;\n```\n\n## Container Types\nFollowing container types are available in FroLang:\n\n### Array\n- Represents a collection of elements\n- Elements of a FroLang array can be of completely different types\n- Multi-dimensional arrays are also supported\n- Array elements are ordered by their index and index starts from 0\n- Arrays in FroLang are immutable\n- Truthy value: Non empty array (contains at least 1 element)\n\n**Example**\n```js\nlet items = [1, 2.5, true, \"Go\", [1, 2]];\nlet lastItem = items[4][1];\n```\n\n### Hash\n- Represents dictionary that can store key-value pairs\n- Keys of a hash must be of primitive type (hash-able)\n- Keys of a hash is unordered\n- Values can be of any type\n- Retrieve value from a hash using the key as the index\n- Truthy value: Non empty hash (contains at least 1 key)\n\n**Example**\n```js\nlet passwordDict = {\"gmail\": 123, \"fb\": 456};\nlet fbPassword = passwordDict[\"fb\"];\n```\n\n## Functions\n- Functions in FroLang are fist class citizens\n- Functions are created using `fn` keyword\n- FroLang as of now doesn't support default arguments\n- Functions in FroLang does create `closures`\n- Functions in froLang implicitly returns the value of last statement\n- You can explicitly return from anywhere within the body using `return` keyword\n\n**Example**\n```js\nlet speak = fn(prefix) {\n    let sep = \"\u003e\u003e\";\n    return fn(message) { prefix + sep + message }\n};\n\nprint(speak(\"Bot\")(\"Hello World\"));\n```\n\n## Operators\nFollowing operators are supported by FroLang:\n\n### Arithmetic operators\n| Operator | Description | Operands | Example |\n|-|-|-|-|\n|__+__|Sum|integer/float|`let sum = 3 + 1;`|\n|__-__|Subtract|integer/float|`let diff = 3 - 1;`|\n|__*__|Multiply|integer/float|`let prod = 3 * 2;`|\n|__/__|Divide|integer/float|`let quot = 6 / 2;`|\n\u003e 💡In case of arithmetic operation, if any of the operand is having float value, then the result of the operation will also be a float value \n\n### String operators\n| Operator | Description | Operands | Example |\n|-|-|-|-|\n|__+__|Concatenate|string|`let msg = \"Mocha\" + \"Tek\";`|\n\n### Conditional operators\n| Operator | Description | Operands | Example |\n|-|-|-|-|\n|__\u003c__|Less than|int/float|`let res = 3 \u003c 4;`|\n|__\u003e__|Greater than|int/float|`let res = 3 \u003e 4;`|\n|__\u003c=__|Less than or equal|int/float|`let res = 3 \u003c= 4;`|\n|__\u003e=__|Less than or equal|int/float|`let res = 3 \u003e= 4;`|\n|__==__|Equality|any|`let res = 3 == 4;`|\n|__!=__|Inequality|any|`let res = 3 != 4;`|\n\n\u003e 💡== and != returns boolean value. It compares the value of operands in case of primitive types, whereas it compares the reference in case of containers. Therefore, [1, 2] will not be equal to [1, 2]\n\n\u003e 💡Comparison like: (2.0 == 2) will evaluate to true, but (2.1 == 2) will not\n\n### Logical operators\n| Operator | Description | Operands | Example |\n|-|-|-|-|\n|__!__|Not - negates the truth value|any|`let res = !true;`|\n|__\u0026__|And - evaluates the first falsy value. If both are truthy/falsy, it will evaluate the right operand|any|`let res = true \u0026 true;`|\n|__\\|__|Or - evaluates the first truthy value. If both are truthy/falsy, it will evaluate the right operand|any|`let res = true \\| false;`|\n\n### Presence operators\n| Operator | Description | Operands | Example |\n|-|-|-|-|\n|__in__|Check if an element exists in a sequence or not|string/array/hash|`let res = \"a\" in \"FroLang\";`|\n\n\u003e 💡In case of hash, the _in_ operator looks for the key rather than value as in string/array\n\n## Conditionals\n- FroLang only has if and else. It doesn't have any elif or else if like in other languages\n- In FroLang, you can use `if - else` as an expression to mimic a ternary operation\n- Parentheses `()` around the condition is optional in FroLang\n\n**Example**\n```js\nlet name = \"Ronaldinho\";\nlet goals = 5;\nlet rank = if goals \u003e= 3 { 1 } else { 2 };\n\nif(rank == 1) {\n    print(name + \" won 🥇\");\n} else {\n    if goals {\n        print(name, \" won 🥈\");\n    } else {\n        print(name + \" won 🥉\");\n    }\n};\n```\n\n## Loops\nFroLang supports  `for in` and `while` loop for iteration\n\n### For in Loop\n- Used to iterate through each element of a sequence\n- In case of hash, iterating element is the key\n- For looping _n_ times, you can use `range(start, end)` to create a sequence of length: n\n- Parentheses `()` around the loop expression is optional in FroLang\n\n**Example**\n```js\nlet string = \"FroLang\";\nfor (char in string) {\n    print(char);\n}\n\nlet array = [\"Pen\", 5];\nfor element in array {\n    print(element);\n}\n\nlet hash = {\"fb\": 123, true: \"Valid!\"};\nfor (key in hash) {\n    print(key, hash[key]);\n}\n\n/* n = 2 */\nfor i in range(1, 3) {\n    print(\"count\", i);\n}\n```\n\n### While Loop\n- Used to execute a block of code while a specified condition is true\n- Parentheses `()` around the condition is optional in FroLang\n\n**Example**\n\n```js\nlet count = 1;\nwhile count \u003c 3 {\n    print(count);\n    count = count + 1;\n}\n```\n\n## Jump Statements\n- Jump statements transfer control of the program to another part of the program\n- FroLang contains 2 jump statements: `break` and `continue` which serve the same purpose as in other languages\n- Jump statements in FroLang can only be used inside loop body\n\n**Example**\n```js\nlet count = 0;\nprint(\"Counting from 1 to 5\");\n\n while count \u003c= 5 {\n    count = count + 1;\n    if count == 2 {\n        print(\"Skipping 2\");\n        continue;\n    }\n    if count == 4 {\n        print(\"Stopping at 4\");\n        break;\n    }\n    print(count);\n}\n```\n\n## Error Handling\n- FroLang provides error handling mechanism to catch runtime errors using try-catch-finally block\n- The `try` statement defines a code block to run (to try)\n- The `catch` statement defines a code block to handle any error from try block\n- The `finally` statement defines a code block to run regardless of the result\n- Catch block is mandatory whereas finally is optional\n- Parentheses around the caught error in catch is optional\n\n**Example**\n\n```js\ntry {\n    print(\"Trying to divide 10 by 0\")\n    let quot = 10/0;\n} catch error {\n    print(error)\n} finally {\n    print(\"Done\")\n}\n```\n\n## Builtin Methods\n|Method|Description|Example|\n|-|-|-|\n|_print(...args)_|Prints arguments to stdout separated by space|`print(\"Hello \", \"World\")`|\n|_type(arg)_|Returns the type of the argument|`type(1)`|\n|_str(arg)_|Returns the stringified form of the argument|`str([1, 2])`|\n|_len(iterable)_|Returns the length of a string/array/hash|`len(\"FroLang\")`|\n|_reversed(str_or_array)_|Reverse the order of elements in a string/array|`reversed(\"FroLang\")`|\n|_slice(str_or_array, start, end)_|Returns a slice from start to end index of a string/array. End index is exclusive|`slice(\"MochaTek\", 0, 5)`|\n|_range(start, end)_|Returns an integer array with elements ranging from start to end. End is exclusive|`range(0, 5)`|\n|_lower(str)_|Returns the lower case representation of a string|`lower(\"HeLlO\")`|\n|_upper(str)_|Returns the upper case representation of a string|`upper(\"HeLlO\")`|\n|_split(str)_|Returns an array with characters of a string as elements|`split(\"FroLang\")`|\n|_join(array, sep=\", \")_|Returns a string created by combing array elements separated by _sep_, which is _\", \"_ by default|`join([\"F\", \"r\", \"o\", \"L\", \"a\", \"n\", \"g\"], \"\")`|\n|_push(array, ...elements)_|Returns a new array with elements inserted at the end|`push([1, 2], 3, 4)`|\n|_pop(array)_|Returns a new array with the last element removed|`pop([1, 2, 3])`|\n|_unshift(array, ...elements)_|Returns a new array with elements inserted at the beginning|`unshift([3, 4], 1, 2)`|\n|_shift(array)_|Returns a new array with the first element removed|`shift([1, 2, 3])`|\n|_keys(hash)_|Returns an array of keys in a hash|`keys({1: \"one\", \"two\": 2})`|\n|_values(hash)_|Returns an array of values in a hash|`values({1: \"one\", \"two\": 2})`|\n|_delete_(hash, key)_|Returns a new hash with the key-value pair removed for the supplied key|`delete({1: \"one\", \"two\": 2}, 1)`|\n\n## To-Do\n- [ ] Environment variables\n- [ ] Modules\n- [ ] StdLib: `datetime, fileIO`\n- [ ] Help\n- [ ] Example programs\n- [ ] Compiler\n\n# Reference\n\n[Writing An Interpreter In Go](https://interpreterbook.com/) by Thorsten Ball\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochatek%2Ffrolang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmochatek%2Ffrolang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochatek%2Ffrolang/lists"}