Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# The Gom Programming Language

**Gom** is a statically typed, multi-paradigm programming language based on a subset of the ECMAScript (and Rust) syntax but providing type-safety and concise syntax. It can be interpreted or compiled to C code or LLVM IR. It takes inspiration from AssemblyScript and makes it more approachable to learn compiler construction.
**Gom** is a statically typed, compiled programming language based on a subset of TypeScript's syntax. Imagine writing TypeScript, but instead of compiling to JavaScript, it compiles to LLVM IR which can then be compiled directly to machine code.

Here’s a typical hello world program in Gom:

```ts
import io;

fn main() {
function main() {
io.log("Hello, world!");
}
```
Expand All @@ -19,29 +19,31 @@ Simple arithmetic and function declaration looks like this:
```ts
import io;

fn add(a: int, b: int): int {
function add(a: int, b: int): int {
return a + b;
}

fn main() {
function main() {
io.log("Sum:", add(1, 2)); // Prints "Sum: 3"
}
```

Defining complex data structures is possible via the `struct` notation (like `struct` in C/Rust/Go). `let` is the variable declaration keyword, it infers type from the expression on the right hand side of `=`.
Defining complex data structures is possible via the `type` keyword. `let` is the variable declaration keyword, it infers type from the expression on the right hand side of `=`.

```ts
import io;

// List
type Numbers = [int];

// Struct
type Temperature = {
high: int,
low: int,
avg: int
};

fn main() {
function main() {
let a = 1; // type inferred as int
io.log("a: ", a);

Expand All @@ -60,7 +62,7 @@ fn main() {
}
```

Apart from the built-in types, custom types can be created using the `type` keyword.
Other types can be defined using the `type` keyword.

```ts
type Count = int;
Expand Down
2 changes: 1 addition & 1 deletion examples/hello_world.gom
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import io;

fn main() {
function main() {
io.log("Hello, World!");
}
2 changes: 1 addition & 1 deletion examples/list.gom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Status = {
type StatusList = [Status];
type Pairs = [{ int, int }];

fn main() {
function main() {
let numbers = Numbers { 1, 2, 3, 4, 5 };

let i = 0;
Expand Down
2 changes: 1 addition & 1 deletion examples/loop.gom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import io;

fn main() {
function main() {
let i = 0;
for (i = 0; i < 10; i = i + 1) {
io.log("i: ", i);
Expand Down
16 changes: 16 additions & 0 deletions examples/methods.gom
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import io;

type Status = {
code: int,
success: bool,

function print() {
io.log("Status { code: ", code, ", success: ", success, " }");
}
};

function main() {
let status = Status { code: 200, success: true };
io.log("Printing status:");
status.print();
}
2 changes: 1 addition & 1 deletion examples/readme.gom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Temperature = {
avg: int
};

fn main() {
function main() {
let a = 1; // type inferred as int
io.log("a: ", a);

Expand Down
4 changes: 2 additions & 2 deletions examples/recursion.gom
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import io;

fn power_n(x: int, n: int): int {
function power_n(x: int, n: int): int {
if (n == 0) {
return 1;
}
return x * power_n(x, n - 1);
}

fn main() {
function main() {
io.log("Hello, World!");
io.log("2^3 = ", power_n(2, 3));
}
8 changes: 4 additions & 4 deletions examples/test_2.gom
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ type Line = {

let GLOBAL = 1;

fn square(x: int): int {
function square(x: int): int {
return x * x;
}

fn add(a: int, b: int): int {
function add(a: int, b: int): int {
return a + b;
}

fn distance(p1: Point, p2: Point): int {
function distance(p1: Point, p2: Point): int {
return square(p1.x - p2.x) + square(p1.y - p2.y);
}

fn main() {
function main() {
let p1 = Point { x: 1, y: 2 }, p2 = Point { x: 3, y: 4 };
let d = distance(p1, p2);
io.log("Distance between p1 and p2: ", d);
Expand Down
6 changes: 3 additions & 3 deletions examples/test_3.gom
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import io;
type HttpResponse = { int, bool };


fn process_http(url: str): HttpResponse {
function process_http(url: str): HttpResponse {
if(url == "http://www.example.com") {
return { 200, true };
}

return { 401, false };
}

fn process_http_retry(url: str, retries: int): HttpResponse {
function process_http_retry(url: str, retries: int): HttpResponse {
let i = 0;
for(i = retries; i > 0; i = i - 1) {
io.log("Round: ", retries - i + 1);
Expand All @@ -25,7 +25,7 @@ fn process_http_retry(url: str, retries: int): HttpResponse {
return { 500, false };
}

fn main() {
function main() {
let resp = process_http_retry("http://www.example.com", 10);
io.log("Status: ", resp.0, " Success: ", resp.1);
}
4 changes: 2 additions & 2 deletions gom.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ typeOrFunctionDefinition = typeDefinition | functionDefinition;

typeDefinition = "type" , identifier , "=" , gomType , ";";

functionDefinition = "fn" , identifier , "(" , argumentItem* , ")" , functionReturnType? ,
functionDefinition = "function" , identifier , "(" , argumentItem* , ")" , functionReturnType? ,
"{" , statement+ , "}";

mainFunction = "fn" , "main" , "(" , argumentItem* , ")" , functionReturnType? ,
mainFunction = "function" , "main" , "(" , argumentItem* , ")" , functionReturnType? ,
"{" , statement+ , "}";

statement = ifStatement
Expand Down
2 changes: 1 addition & 1 deletion gom_modules/io/index.gom
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export fn hello() {
export function hello() {

}
6 changes: 3 additions & 3 deletions src/lexer/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export enum GomToken {
IMPORT = "import",
EXPORT = "export",
TYPE = "type",
FN = "fn",
FN = "function",
LET = "let",
CONST = "const",
FOR = "for",
Expand Down Expand Up @@ -57,7 +57,7 @@ export const GOM_KEYWORDS = new Set([
"import",
"export",
"type",
"fn",
"function",
"let",
"const",
"for",
Expand All @@ -77,7 +77,7 @@ export const getKeywordType = (value: string): GomToken => {
return GomToken.EXPORT;
case "type":
return GomToken.TYPE;
case "fn":
case "function":
return GomToken.FN;
case "let":
return GomToken.LET;
Expand Down
2 changes: 1 addition & 1 deletion src/semantics/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* - Tuple, e.g. (int, bool)
* - Struct e.g. { x: int, y: int }
* - Composite, e.g. type IntList = List<int>
* - Function, e.g. fn add(a: int, b: int): int
* - Function, e.g. function add(a: int, b: int): int
*
* For now, structs are not supported & custom types can only be aliases to primitives.
*/
Expand Down
8 changes: 4 additions & 4 deletions test.gom
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ type Point = struct {

let GLOBAL = 1;

fn square(x: i8): i8 {
function square(x: i8): i8 {
return x * x;
}

fn add(a: i8, b: i8): i8 {
function add(a: i8, b: i8): i8 {
return a + b;
}

/*
Print numbers from 0 to n
*/
fn print_to_n(n: i8) {
function print_to_n(n: i8) {
let i = 0;
for(; i < n; i = i + 1) {
io.log("i:", i);
}
}

fn main() {
function main() {
let a = 1 + 2, b = 2;

io.log("Sum:", add(1, (1 + b / 2)));
Expand Down
Loading