<img height="64" src="frg-icon.png">
*The best programming language since it's named after frogs*
# Table of Contents
1. [Showcase](#showcase)
2. [Purpose](#purpose)
3. [Features](#features)
4. [Installation](#installation)
5. [Editor Setup](#editor-setup)
6. [Usage](#usage)
7. [Style Guide](#style-guide)
# Showcase
```rs
struct Frog = {
str name,
int age,
int leg_count,
}
int(&Frog) jump = (jumping_frg) {
if jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1
}
jumping_frg.leg_count
}
map(str, int) frog_ages = { "greg": 2, "grog": 1, "josch": 712 }
vec(Frog) swamp = []
Frog wisest_frg = { name: "NONE", age: 0, leg_count: -1 }
frog_ages.iter().for_each((elem) {
Frog new_frg = {
name: elem.0.*
age: elem.1.*,
leg_count: 4,
}
if new_frg.age > wisest_frg.age {
wisest_frg = new_frg.clone()
}
swamp.push(new_frg)
})
int jumps_remaining = jump(&wisest_frg)
@print("{jumps_remaining} jumps left on {}", wisest_frg.name)
```
# Purpose
frg was made for one reason:
- *The silly factor*
Basically i took some Rust code, and sillyfied it. Heres an example
```rs
fn jump(jumping_frg: &mut Frog) -> i32 {
if jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1;
}
jumping_frg.leg_count
}
```
First, remove anything that doesn't have to be there in order to function. This includes any commas, semicolons, keywords, stuff like that
```rs
fn jump(jumping_frg: &Frog) -> i32 {
jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1
}
jumping_frg.leg_count
}
```
Next, seperate the declaration from the implementation (make it a closure)
```rs
// we still keep types!!
let jump: fn(&Frog) -> i32 = |jumping_frg| {
jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1
}
jumping_frg.leg_count
}
```
Lastly, rearrange everything and hide the exact data type (i32 -> int)
```rs
int(&Frog) jump = (jumping_frg) {
jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1
}
jumping_frg.leg_count
}
```
You don't like not having an if keyword? Does that make you annoyed? Have three.
```rs
int(&Frog) jump = (jumping_frg) {
if if if jumping_frg.leg_count > 0 {
jumping_frg.leg_count -= 1
}
jumping_frg.leg_count
}
```
You want to add another parameter? And a loop? Your greed is insulting.
```rs
int(&Frog, ,int) jump = (jumping_frg jump_count,,) {
if if if jumping_frg.leg_count - jump_count >= 0 {
// rust styled loops because theyre objectively better
(0..=jump_count).for_each((_) {
jumping_frg.leg_count -= 1
@print("{} legs remaining", jumping_frg.leg_count)
})
}
jumping_frg.leg_count
}
```
If you're insecure about the size of your -= or your >=, you should be, but also frg is perfect for you!
```rs
int(&Frog, ,int) jump = (jumping_frg jump_count,,) {
if if if jumping_frg.leg_count - jump_count >>>==== 0 {
jumping_frg.leg_count --====== jump_count
}
jumping_frg.leg_count
}
```
If you can't comprehend the last expression in a function being the returned value, you can use the `return` keyword.
```rs
return jumping_frg.leg_count
```
"Oh but how does it know when one statement ends and one begins! I don't have my fucking semicolons!". This system works on hopes and dreams and is flawless.
```rs
int your_iq = 5 int(int int) recalc = (value_a value_b) { return value_a - value_b } your_iq -= recalc(,,112 your_iq)
```
But you can add semicolons if you want i guess.
```rs
int your_iq = 5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
```
> [!NOTE]
> semicolons can be used to guide treesitter since its stupid and needs them sometimes :(
## More examples
Take some normal rust code, for example a vector declaration.
```rs
let mut number_list: Vec<i32> = vec![5, 8, 8, 9 - 3]
number_list[2] -= number_list[0]
```
(do everything above)
And done! Ideal frg code!
```rs
vec(int ) number_list = [,5 8 8 9 - 3]
number_list [[[ 2] ---==== number_list [ 0 ]]]
```
The parser will not trust you after this one.
# Features
## Types
- Integers (`int`)
- Floats (`float`)
- Strings (`str`)
- Booleans (`bool`)
- Vectors (`vec(int)`)
- Maps (`map(str, int)`)
- Functions (`int(str)`)
- Structs (`StructName`)
- References (`&int`)
These type aliases since you'll forget `map` somehow:
- `map`: `obj`, `hashmap`, `dict`, `dictionary`
- `vec`: `array`, `arr`, `list`
## Plagiarized
Some pointer bullshit you can probably pull off (from C):
```rs
// this is one of the tests in this projects
&people[get_index()].pets[0].* += calculate(x.* + y[2] - z.age / 3 * 2) >= threshold * active
```
Functions as values (from Java i think):
```rs
// this is also a test
int(float, str)(map(str, int())) average_java_developer = (get_score_map) { (my_int, my_float) { 5 } }
```
Parentheses (invented by Lisp):
```rs
(5)
```
Semicolons (invented by javascript because i hate javascript and i hate semicolons):
```rs
// scroll up to the part about semicolons i hate talking about them more than i need too
```
STRUCTS!! FROM HIT LANGUAGE RUST!!
```rs
struct Person = {
int age,
str name,
}
Person josch = {
age: 912,
name: "ojshsc"
}
```
Dereferencing from Zig bc that syntax is nicee
```rs
&int var = &5
void(&int) increment = (to_update) {
to_update.* += 1
}
increment(var)
```
## If Statements
Keywords? I think? im not sure i blacked out when i was adding this part. this code might ont even run but its in my tests (from python? maybe lua?)
```rs
if thing {
} else if other_thing {
} else {
}
```
wait no keywords are optional
```rs
if if if thing {
} else else else if if other_thing {
} else if if {
}
```
> [!NOTE]
>
> `else` is required due to technical limitations (treesitter).
> Getting rid of `if` is fine though.
> ```
> thing {
> } else other_thing {
> } else {
> }
> ```
## Structs and Maps
also maps and structs share the same syntax so they have to be declared in their declaration
```rs
// THIS IS FINE
Frog frg = { name: "frg", legs: 8, age: 3 }
map(str, int) slur_count = { "fuck": 9857, "shit: 8234", "i dont like rust": 494 }
// THIS WONT WORK
frg = { name: "no", legs: -199999, age: 94787367 }
slur_count = { "error": 9001 }
// I THINK REASSIGNING THEM IS FINE THOUGH
Frog frg = { name: "not frg", legs: -8, age: -3 }
map(str, int,, ) slur_count = { "darn": 9840928341 }
```
You can declare struct literals like its Rust if you need them inline:
```rs
Frog new_frg = mitose(Frog { name: "freg", legs: 1, age: 80 })
```
Also from Zig, builtins:
`@print`: Uses Rust's string interpolotation to `println!`
`@<type>`: Try casting to a certain BUILT IN type
## treesitter is begging for its dear life
Basically anytime you see something that doesn't need to be there you can probably remove it. Or add extra.
```rs
// example: commas in maps
map(float, int) round_table = {
0.0: 0,,,,,
0.1: 0,,
0.2: 0,
0.3: 0
0.4: 0
0.5: 1,
0.6: 1,,
0.7: 1,,,,,
0.8: 1,,,,,,
0.9: 1,,,
1.0: 1,
}
```
## Voiding Values
When you call a function, its required to use all of it's values. If you don't need to use them, assign them to the special `_` variable, which discards its value when its set:
```rs
_ = returns_value()
```
Theres a special keyword for this action: `void`
```rs
void returns_value()
```
Yes, it's the same void as the type.
> [!NOTE]
> The void keyword is optional
> ```rs
> returns_value()
> ```
# Installation
> [!IMPORTANT]
> Rust is required to use this project.
> You can install Rust through [the official website](https://rust-lang.org/tools/install/).
## Cargo (Recommended)
*You need Rust installed to use this project anyways.*
1. `cargo install frg`
2. Only 29 dependencies, installs quickly and works on any platform
3. Execute with `frg` anywhere
## Linux
1. Go to the [latest release](https://github.com/Shuflduf/frg/releases/latest)
2. Download `frg-linux-[ARCH]`
3. Rename to `frg`
4. Execute with `./frg` while in the directory with the binary
## MacOS
1. Go to the [latest release](https://github.com/Shuflduf/frg/releases/latest)
2. Download `frg-macos-[ARCH]`
3. Rename to `frg`
4. Execute with `./frg` while in the directory with the binary
## Windows
1. Go to the [latest release](https://github.com/Shuflduf/frg/releases/latest)
2. Download `frg-windows-[ARCH].exe`
3. Rename to `frg.exe`
4. Execute with `frg.exe` while in the directory with the binary
# Editor Setup
## Helix
1. Add this to your `languages.toml`:
```toml
[[grammar]]
name = "frg"
source = { git = "https://github.com/Shuflduf/frg", rev = "*", subpath = "tree-sitter-frg" }
[[language]]
name = "frg"
scope = "source.frg"
file-types = ["frg"]
comment-tokens = ["//"]
indent = { tab-width = 4, unit = " " }
```
2. Run `helix --grammar fetch` and `helix --grammar build`
## VSCode
1. Download the extension from [OpenVSX](https://open-vsx.org/extension/Shuflduf/frg)
<img height="100" src="https://github.com/user-attachments/assets/b68c7ce1-140c-4bc0-98b2-e8edf2485b27" />
2. Go the extensions panel in the sidebar (`Ctrl + Shift + X`)
3. Open the three-dot menu and select `Install from VSIX`
<img height="200" src="https://github.com/user-attachments/assets/5d517ff2-40b2-4cc3-bbda-c6249fbf5d33" />
4. Select the downloaded extension.
# Usage
Invoke the binary with its name, usually `frg`.
```
frg Transpiler and Runner (v2.0.0)
Usage: frg [FILE]
Options:
-h, --help Print this help menu.
-v, --verbose Show input code and intermediary treesitter, AST, and Rust.
-n, --no-exec Don't run generated Rust. Usually used with -v.
-e, --example Run an example. No args provided will list the examples.
Examples:
frg my_code.frg Execute a frg file.
frg --example List examples
frg -e fibonacci Run the fibonacci example
frg -v -n my_code.frg Show the process of a frg file being turned into Rust.
```
To write your own frg code, use your [editor](#editor-setup) of choice, and add anything you want to a text file.
Having the file extension be `.frg` is not required, but is recommended.
If something isn't working as expected, use the `-v` flag to inspect the generated Rust to see if everything works.
## Examples
- `fibonacci`: Calculate a target fibonacci number
- `factorial`: Calculate a target factorial number
- `primes`: Lists numbers 1 - 50 and tells you if they're prime
- `guessing`: Higher or lower guessing game, this is the BIG one you SHOULD TEST
# Style Guide
fuck around and find out