Skip to content

zesterer/forge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Forge

Forge is a dynamically-typed language written in Rust. It is inspired by JavaScript, Rust, Python and Rhai. In the future, you'll be able to use Forge as a general-purpose lightweight scripting language in your applications.

You can try out Forge in your browser here!

Example

# A function to square numbers
var square = |x| {
	return x * x;
};

var n = input "How many squares? ";

# Create a list of squares
var squares = [];
for x in 1..n + 1 {
	squares += square(x);
}

# Iterate and print squares
for square in squares {
	print square;
}

Goals

  • Simple, familiar syntax
  • Lightweight, quick to parse
  • Moderately fast execution speeds
  • Well-considered, 'common-sense' design
  • Useful, informative error messages
  • Easy to build into an existing codebase
  • Python-like REPL prompt

Usage

Using Forge is similar in principle to using Python. Once compiled, running the shell or executing scripts with the interpreter is trivial. You'll need to compile the cli/ crate to gain access to the interpreter binary.

To access the REPL shell, run:

$ forge

To execute a script, run:

$ forge my_script.fg

Roadmap

  • Numbers, strings and booleans
  • Arithmetic operators +, -, *, /, %
  • Logical operators and, or, xor, ==, !=, !, <, <=, >, >=
  • if/else statements
  • while and for statements
  • Assignment operators =, +=, -=, *=, /=, %=
  • Scoped variable declaration
  • Function objects
  • Function calling
  • Rust-to-Forge object interface
  • Rust-to-Forge type coercion
  • Rust callbacks Only Rust closures with no arguments or functions are currently supported
  • Iterators
  • Rust-to-Forge iterators
  • Lists
  • List splicing
  • Indexing and ranges
  • clone and mirror operators
  • Lvalues vs rvalues
  • Maps
  • Map construction
  • Map iteration
  • Immutability by default
  • Structures
  • Enums
  • Objects
  • Modules as objects
  • Scoped constants
  • C-based FFI for non-Rust integration
  • AST optimisation
  • Bytecode generation
  • Bytecode interpretation
  • LLVM-driven recompilation

Some Syntax Examples

List splicing

>> var my_list = [0, 1, 2, 3];
>> my_list[1..2]
[1]
>> my_list[1..3] = ["this", "is", "a", "list", "splice"];
>> my_list
[0, this, is, a, list, splice, 3]

String splicing

>> "Hello, world!"[7..12]
world
>> var test = "An apple is what I am eating";
>> test[3..8] = "pear";
>> test
An pear is what I am eating
>>

Design

Types

Forge has several distinct types:

  • Number 64-bit, floating-point
  • String unicode-compliant
  • Char unicode-compliant
  • Boolean
  • Range
  • Function
  • List
  • Map
  • Object Currently unimplemented
  • Custom Used to call to and from Rust
  • Null

Things To Do

  • Investigate design features that would make the dynamic type system easier to optimise

Interpreter

Currently, Forge is only implemented as an AST-walking interpreter. In the future, I aim to generate more efficient low-level bytecode for the language. I also aim to implement many a variety of optimisations throughout the compilation process.

Error Messages

Forge aims to produce the most useful, informative and intelligence error messages it can. Errors can be emitted at compile-time or run-time. Below are a few examples.

Parser errors:

[ERROR] Parsing error at 1:45...
   ...while parsing if-else statement...
   ...while parsing print statement...
        1| var x = 1; if x > 2 { print "Hello, world!" oops; }
         |                                             ^^^^
   Expected ';', found identifier 'oops'.

Runtime errors:

[ERROR] Runtime error at 1:21...
        1| var p = true; while p { print "On the next iteration, p will be null"; p = null; }
         |                     ^
   Cannot determine the truthiness of value of type 'null'. Did you mean for this to be a bool?

Runtime errors that produce error messages that reference code written during the previous declaration of a function object:

[ERROR] Runtime error at 1:10...
        1| var say_hello = || { print "Hello, world!"; };
         |                 ^^
        1| say_hello(1); # Wrong number of parameters
         |          ^^^
   Tried to call a function with the wrong number of parameters. Expected 0, found 1.

About

A lightweight, elegant scripting language with built-in Rust-FFI.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages