https://github.com/a1exwang/wtf-interp
An functional scripting language inspired by Ruby, Elixir, CoffeeScript, Python, etc
https://github.com/a1exwang/wtf-interp
functional-programming interpreted-programming-language language ruby wtf
Last synced: 4 months ago
JSON representation
An functional scripting language inspired by Ruby, Elixir, CoffeeScript, Python, etc
- Host: GitHub
- URL: https://github.com/a1exwang/wtf-interp
- Owner: a1exwang
- License: mit
- Created: 2016-08-03T09:59:29.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-06-05T08:46:19.000Z (over 8 years ago)
- Last Synced: 2025-07-13T13:43:20.215Z (4 months ago)
- Topics: functional-programming, interpreted-programming-language, language, ruby, wtf
- Language: Ruby
- Homepage:
- Size: 120 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
### An interpreted language inspired by Ruby, Elixir, CoffeeScript, Python, etc
##### Learn from Examples
- Basic Data Types
```
# Integers
a = 1;
# Strings
b = "abc";
# Lists
lst = [1, 2, 5, "hello world"];
each(lst, -> (item) { puts(item); });
puts(lst[3]);
# 2D list
lst1 = [[1, 3, 5],
[2, 4, 6],
[3, 5, 7]];
puts(to_s(lst1[0][0]));
# Booleans and Nil
puts([True, False, Nil]);
# Hash Map
map = {a: 2 + 3};
puts(map["a"]);
# Functions
puts(Type::is_a(1, Type::Int));
puts(Type::is_a(1, Type::Float));
puts(Type::is_a(Type::is_a, Type::Function));
```
- Operators
```
puts(-1);
puts(1 + 2);
puts(1 - 2);
puts(1 * 2);
puts((3 + 4) * 5);
puts("abc" == "abc");
puts("abc" != "abcd");
puts("abc" != 1);
puts(Nil == Nil);
puts(1 > 2);
puts(1 >= 1);
```
- Basic Statements
```
puts(
if (True) {
"true";
} else {
"false";
}
);
```
- Functions as First Citizens
```
fn = ->() { -> () { "fn"; }; };
fn1 = ->(x, *args) {
x + args[0] + args[1] + args[2] + 1;
};
puts(whats(fn));
puts(whats(fn()));
puts(fn()());
puts(fn1(1, 2, 3, 4));
```
- Modules
```
C = module {
B = module {
A = 1;
};
};
puts(C::B::A);
include(C::B);
puts(A);
```
- require() v.s. import()
```
# a.wtf
A = 1
# b.wtf
B = 2
# "require" is like Ruby's require
# It defines all vars of the required file in current bindings
# require.wtf
a = require("./a");
puts(A); # => 1
puts(a); # => 1
# "import" is like Python's import
# It does not affect current bindings,
# but returns a module object containing
# all vars defined in the imported file
# import.wtf
b = import("./b");
puts(b); # =>
puts(b::B); # => 1
```
- Pattern Matching
```
let {a: a} = {a: 1};
let {b: [b, c]} = {b: [2, 3]};
puts(a);
puts(b);
puts(c);
let d = 4;
let {} = {};
let [] = [];
let [{e: e}] = [{e: 5}];
puts(d);
puts(e);
let [f, g, _] = [1, 2, 3];
let [h, i, *j] = [1, 2, 3, 4, 5];
puts(j);
let k, l, m = [4, 5, 6];
puts(k);
let n: {p: p}, o: o = {n: {p: 5}, o: 8};
puts(p);
# case-when statments supports pattern matching
fn = ->(a) {
case (a) {
when (1) {
"a";
}
when ({x: x}) {
x;
}
else {
Nil;
}
};
};
puts(fn(1));
puts(fn({x: "x"}));
puts(fn("abc"));
```
- Exceptions
```
secure {
let [a, b, c, d] = [1, 2, 3];
} rescue {type: type, message: message} {
puts("rescue");
puts(to_s(type));
};
```
- Misc
```
# "eval" is not so "evil"
puts(eval("-> { puts(2+3); }")());
# Command Line Arguements
puts(ARGV);
```
### TODOs
- syntax
- regex
- map pattern matching on fn_def
- if no-else, if elsif else
- stdlib
- math
- io
- promise
### Language Design
1. Main Goals
1. Make the programmers happy.
1. Functional.
1. What-you-see-is-what-you-get syntax.
1. Simple basic syntax plus syntax sugars.
1. Code fast, cod short.
1. Do not refactor, rewrite it.
1. Ruby inter-ops.
1. Threads are shit.
### Design Details
- wtf.rb
- Interpret executable
- lexer.rb
- Lexer
- parse.y
- yacc-like parser
- eval.rb
- Implement "eval"-like functions in Ruby
- e.g. eval(str), require(file), import(file)
- vm.rb
- Interpreter virtual machine
- The virtual machine executes AST nodes
- api.rb
- Ruby inter-ops
- ast/nodes.rb
- AST Node definitions
- stdlib/kernel.rb
- Basic wtf data types and kernel functions in Ruby
- How the interpreter runs your code
1. Parser runs, and drives the lexer. Generate an AST.
- Each node knows its children
1. AST traversal 1
- Each node knows its parent, and the interpreter knows the entry point
1. Evaluate the AST node of the "main" function
- Ruby and wtf objects
1. Each wtf object type is a WtfType objects
1. wtf exception is Ruby Wtf::Lang::Exception::WtfError
- Bindings
1. Bindings change only at function or module definitions or ensure..rescue block