Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/doc/
bin/farpy
/tests/a.ts
/tests/a.php
/tests/click.ts
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ build:

install: build
@echo "Copying the binary to $(DESTDIR)..."
@sudo cp $(BUILD_PATH) $(DESTDIR)
@sudo cp -f $(BUILD_PATH) $(DESTDIR)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ farpy -v
- Control flow structures (if)
- Built-in constants

### In Progress 🚧
### In Progress 🚧

- Type System
- Complex types (objects, arrays, vectors)
Expand Down Expand Up @@ -113,7 +113,7 @@ All PRs will be reviewed by the main maintainer (fernandothedev).

MIT License

```
```
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
Expand Down
6 changes: 4 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"tasks": {
"compile": "deno compile -A -o bin/farpy main.ts"
"compile": "deno compile -A -o bin/farpy main.ts",
"compile_self": "deno compile -A main_compile.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@^1.0.11",
"@std/cli": "jsr:@std/cli@^1.0.13"
"@std/cli": "jsr:@std/cli@^1.0.13",
"@std/path": "jsr:@std/path"
}
}
25 changes: 23 additions & 2 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions examples/array.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
new arr: array = { 1, 2, 3 }
print(arr)
17 changes: 17 additions & 0 deletions examples/exotic.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
new mut name: string = "Fernando" print(name) new lambda: void = fn |name|(): void { name = "Cabral" print(name) } lambda() print(name)

/**
new mut name: string = "Fernando"

print(name)

new lambda: void = fn |name|(): void
{
name = "Cabral"
print(name)
}

lambda()

print(name)
*/
7 changes: 1 addition & 6 deletions examples/fib.farpy
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
fn fibonacci(n: int): int
{
if n <= 0 {
return 0
} elif n == 1 {
return 1
}

if n <= 1 { return n }
return fibonacci(n - 1) + fibonacci(n - 2)
}

Expand Down
21 changes: 21 additions & 0 deletions examples/fib_new.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import map as m

new map: map = m.Map()

fn fibonacci(n: int): int
{
if map.has(n)
{
return map.get(n)
}

if n <= 1
{
return n
}

map.set(n, fibonacci(n - 1) + fibonacci(n - 2))
return map.get(n)
}

print(fibonacci(100))
13 changes: 13 additions & 0 deletions examples/for.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import io

new name: string = "Fernando"
new mut sum: int = 0

for new mut i: int = 0; i < name.length(); i++ {
print(name.at(i))
}
for i = 0; i < 100; i++ {
sum = sum + i
}

print(io.format("Sum = {sum}"))
2 changes: 2 additions & 0 deletions examples/import.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import io
import math as m
7 changes: 7 additions & 0 deletions examples/io.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import io
import utils

new name: string = io.readline("Name:")
new age: int = utils.toInt(io.readline("Age:"))

print(io.format("Hello {name}, you are {age} years old."))
5 changes: 5 additions & 0 deletions examples/member_call_expr.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
new name: string = "Fernando"

name.at(0).length() // F
name.length() // 8
2 ** name.length() // 256 2⁸
8 changes: 8 additions & 0 deletions examples/member_expr.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import math as m
// import { fibonacci, PI } -> Do in the future

print(m.PI)
print(m.fibonacci(100).len().string())

print(m.PI)

5 changes: 5 additions & 0 deletions examples/member_expr2.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
new str: string = "Fernando is beautiful"
new x: string = str.at(0).length()

print(x)

6 changes: 6 additions & 0 deletions examples/object.farpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
new obj: object = {
name: "Fernando",
age: 17
}

dd(obj.name)
130 changes: 65 additions & 65 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,67 @@ import Context from "./src/runtime/context/Context.ts";
import { parseArgs } from "@std/cli";
import { Colorize } from "./src/utils/Colorize.ts";
import { define_env } from "./src/runtime/context/Context.ts";
import { repl } from "./src/repl.ts";

const parsedArgs = parseArgs(Deno.args, {
alias: {
h: "help",
v: "version",
r: "repl",
o: "output",
},
boolean: ["help", "version", "repl"],
boolean: ["help", "version", "repl", "compile"],
string: ["output", "file"],
});

if (parsedArgs.compile) {
// Compile UWU
if (!parsedArgs.output || !parsedArgs.file) {
console.error("Error: No file specified or output.");
console.error("Usage --output <BINARY> and --file <FILE>.fp");
Deno.exit(1);
}

const file = "main_compile.ts";
const fileData: string = Deno.readTextFileSync(file);
let fileDataTmp = "";

let source: string;
try {
source = Deno.readTextFileSync(parsedArgs.file);
} catch (error: any) {
console.error("Error reading file:", error.message);
Deno.exit(1);
}

fileDataTmp = fileData.replace(`_SOURCE_`, source);
fileDataTmp = fileDataTmp.replace("_FILENAME_", parsedArgs.file);

Deno.writeFileSync(file, (new TextEncoder()).encode(fileDataTmp));

const command = new Deno.Command("deno", {
args: ["compile", "-A", `-o=${parsedArgs.output}`, "main_compile.ts"],
stdout: "piped",
stderr: "piped",
});

const { code, stdout, stderr } = command.outputSync();

if (code === 0) {
console.log(
`${Colorize.green("✓")} Successfully compiled to ${
Colorize.bold(parsedArgs.output)
}`,
);
} else {
console.error(`${Colorize.red("✗")} Compilation failed:`);
console.error(new TextDecoder().decode(stderr));
}

Deno.writeFileSync(file, (new TextEncoder()).encode(fileData));
Deno.exit(1);
}

const VERSION = "v0.1.0";

if (parsedArgs.help) {
Expand All @@ -25,17 +76,20 @@ if (parsedArgs.help) {
farpy [options] <file.farpy>

${Colorize.bold("Options:")}
-h, --help Show this help message.
-v, --version Shows version and runtime information.
-r, --repl Starts the interactive REPL.`,
-h, --help Show this help message.
-v, --version Shows version and runtime information.
-r, --repl Starts the interactive REPL.
-c, --compile Compile a .farpy/.fp file to an executable.
-o, --output <filename> Specify output filename for compilation.
--file <filename> Specify input file for compilation.`,
);
Deno.exit(0);
}

if (parsedArgs.version) {
console.log(
Colorize.bold(
`FarpyScript - ${Colorize.underline(Colorize.blue(VERSION))}`,
`Farpy - ${Colorize.underline(Colorize.blue(VERSION))}`,
),
);
Deno.exit(0);
Expand All @@ -44,64 +98,8 @@ if (parsedArgs.version) {
const context: Context = define_env(new Context());

if (parsedArgs.repl) {
console.log(
Colorize.bold(
`FarpyScript ${Colorize.underline(Colorize.blue(VERSION))} - REPL`,
),
);

let inputBuffer = "";
let balance = 0;
while (true) {
// Se já há conteúdo acumulado, usamos um prompt com padding proporcional ao balance.
const promptSymbol = inputBuffer
? ".".repeat(Math.max((balance * 3) == 0 ? 3 : balance * 3, 1))
: ">";
const line: string = prompt(promptSymbol) ?? "";

if (!inputBuffer && line.trim() === "exit") {
console.log("Bye");
break;
}

// Acumula a linha lida
inputBuffer += line + "\n";

// Atualiza o balance com base na linha atual
for (const char of line) {
if (char === "{") {
balance++;
} else if (char === "}") {
balance--;
}
}

// Evita que o balance fique negativo
if (balance < 0) {
balance = 0;
}

// Se ainda houver blocos abertos, continua a leitura
if (balance > 0) continue;

const code = inputBuffer.trim();
if (code) {
try {
const lexer: Lexer = new Lexer("repl", code);
const tokens: Token[] = lexer.tokenize();
const parser: Parser = new Parser(tokens);
const program: Program = parser.parse();
const runtime: Runtime = new Runtime(context);
runtime.evaluate(program);
} catch (error: any) {
console.error("Error processing code:", error.message);
}
}
// Reseta o buffer e o balance para o próximo bloco
inputBuffer = "";
balance = 0;
}
Deno.exit(0);
repl();
Deno.exit();
}

if (parsedArgs._.length < 1) {
Expand All @@ -112,8 +110,8 @@ if (parsedArgs._.length < 1) {

const file: string = parsedArgs._[0] as string;

if (!file.endsWith(".farpy")) {
console.error("Error: The file must have a .farpy extension");
if (!file.endsWith(".farpy") && !file.endsWith(".fp")) {
console.error("Error: The file must have a .farpy or .fp extension");
Deno.exit(1);
}

Expand All @@ -129,5 +127,7 @@ const lexer: Lexer = new Lexer(file, source);
const tokens: Token[] = lexer.tokenize();
const parser: Parser = new Parser(tokens);
const program: Program = parser.parse();
console.log(program);

const runtime: Runtime = new Runtime(context);
runtime.evaluate(program);
18 changes: 18 additions & 0 deletions main_compile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Lexer } from "./src/frontend/Lexer.ts";
import { Token } from "./src/frontend/Token.ts";
import Parser from "./src/backend/Parser.ts";
import { Program } from "./src/backend/AST.ts";
import Runtime from "./src/runtime/Runtime.ts";
import Context from "./src/runtime/context/Context.ts";
import { define_env } from "./src/runtime/context/Context.ts";

const context: Context = define_env(new Context());
const source: string = `_SOURCE_`;

const lexer: Lexer = new Lexer("_FILENAME_", source);
const tokens: Token[] = lexer.tokenize();
const parser: Parser = new Parser(tokens);
const program: Program = parser.parse();

const runtime: Runtime = new Runtime(context);
runtime.evaluate(program);
Loading