Note
This repository is a fork of the original project by Guilherme. All credit for his hard work belongs to him and only him! I am responsible only for making this README and some other minor things!!!
A compiled, statically and strong typed, inferred, object-oriented programming language written in MiniScript by Guilherme for the game Grey Hack!
All of the above probably doesn't tell you a thing so please take a look at the features below π€π
...Or, if you're already familiar with the language or are too curious, jump straight to the Quick Start π
There are several features Wyvern has to offer, which are shown below along with some simple examples β¨
You can look here and here for more complex thingies! π
Wyvern will back you up and prevent compiling if you've made a mistake πΊ
let a: number = 1;
let b: string = "2";// Compilation error!
// Can't assign number to a string variable
b = 2;// Compilation error!
// Can't summate number and string
print(a + b);// Perfectly fine though!
print(a + cast<number>(b));
// Or even this (0.0 )
print(a + b.val);MiniScript would allow you to run the equivalent code, and if it was a more complex program, you probably wouldn't notice the error until the runtime has taken place! π₯
Implement complex logic in a form of contracts, classes and objects π
contract Plane {
public virtual fn Area() -> number;
public virtual fn Perimeter() -> number;
}
class Figure $ Plane {
public virtual fn Area() -> number;
public virtual fn Perimeter() -> number;
public virtual fn Sides() -> number[];
}
class Triangle: Figure {
private let _a: number;
private let _b: number;
private let _c: number;
private fn _TriangleInequality() -> bool {
if self._a <= 0 || self._b <= 0 || self._c <= 0 {
return false;
}
return (self._a + self._b > self._c) && (self._a + self._c > self._b) && (self._b + self._c > self._a);
}
public override fn Area() -> number {
let p: number = self.Perimeter();
return sqrt(p * (p - self._a) * (p - self._b) * (p - self._c));
}
public override fn Perimeter() -> number {
return (self._a + self._b + self._c) / 2;
}
public override fn Sides() -> number[] {
return [self._a, self._b, self._c];
}
fn Triangle(a: number, b: number, c: number) -> void {
self._a = a;
self._b = b;
self._c = c;
if !self._TriangleInequality() {
exit("Incorrect triangle!");
}
}
}
class Square: Figure {
private let _side: number;
public override fn Area() -> number {
return self._side * self._side;
}
public override fn Perimeter() -> number {
return self._side * 4;
}
public override fn Sides() -> number[] {
return [self._side, self._side, self._side, self._side];
}
fn Square(side: number) -> void {
self._side = side;
}
}
let figures: Figure[] = [
new Triangle(3, 4, 5),
new Triangle(10, 10, 10),
new Square(4),
new Square(13)
];
foreach let figure: Figure in figures {
print([figure.Area(), figure.Perimeter(), figure.Sides()]);
}Everything you know about MiniScript applies here! π₯°
let shell: shell = get_shell();
let computer: computer = shell.host_computer();
let file: file = computer.File("/etc/passwd");
if file != null {
file.delete();
}Not only that, but you can use MiniScript libraries in Wyvern programs! π²
Let's say we have this little library in a hypothetical file called math.src located in /home/user:
Math = {}
Math.classID = "Math"
Math._pi = null
Math.Pi = function
return self._pi
end function
Math.Factorial = function(n)
if n <= 0 then return 1
return self.Factorial(n - 1) * n
end function
Math.New = function
this = new Math
this.classID = "Math"
this._pi = 3.14
return this
end functionThen, to use it in our Wyvern program, we write as follows:
msimport "/home/user/math.src" {
class Math {
public fn Pi() -> number;
public fn Factorial(n: number) -> number;
public static fn New() -> Math;
}
}
let math: Math = Math.New();
print([math.Pi(), math.Factorial(5)]);This allows you to reuse existing code with all the advantages Wyvern has to offer! β€οΈ
Wyvern compiles to the equivalent code in MiniScript ahead-of-time and the runtime performance remains the same as the latter! βοΈ
Simply copy-paste this nice little sequence in your real computer's console (assuming you have Greybel-JS installed and Grey Hack opened) πΎ
git clone https://github.com/shippingfandom/Wyvern ; cd Wyvern ; greybel build src/wyvic/wyvic.ms -id /root -ac -acp -ci
No worries! Follow these simple steps to get your compiler up and running π
- Open Terminal.exe π»
- Type in
sudo -sand pass in your root password πΏ - Type in
FileExplorer.exeand go to the /lib directory π - Right click and choose New Folder. Name it wyvern. Go to it. You should end up in /lib/wyvern by now πΆ
- Right click and choose New File. Name it namespace. Copy the contents of src/wyvern-lang/wyv-namespace.ms to the file you've just created π
Now you have to repeat the step 5 until you have all the needed files in /lib/wyvern... For our own mental health, here is a list of what you have to create and with what you have to populate π€«
| Name in /lib/wyvern/ | Name in src/wyvern-lang/ |
|---|---|
| namespace | wyv-namespace.ms |
| utils | wyv-utils.ms |
| diagnostics | wyv-diagnostics.ms |
| symbols | wyv-symbols.ms |
| syntax | wyv-syntax.ms |
| ast | wyv-ast.ms |
| builtins | wyv-builtins.ms |
| api | wyv-api.ms |
| compiler | wyv-compiler.ms |
| wyvic.src | src/wyvic/wyvic.ms |
Phew! That was an interesting experience! π
Now you have all the project structure in your /lib/wyvern. Double click on /lib/wyvern/wyvic.src, single click at the triangle-like button on the upper left, change the File name to wyvic and press SAVE πΎ
Congratulations! You have installed wyvic - the Wyvern compiler! π
To compile a program made in Wyvern, type wyvern -c YourAwesomeProgram.wyv --build π
The best place to learn some of the Wyvern programming language is Handbook by Guilherme! π₯°
I also highly encourage you to read a short summary of the language, which is written in style of MiniScript one-page summary! π
This is a list of known Wyvern issues. Please do not ask me to fix those, I have no neccessary qualification for this! π
If you try to cast a potentially null value to something non-null, it may result in a runtime error
// Implicitly set to null
let a: string;
// Runtime error!
print(cast<number>(a));let a: any<any> = {1: 2, 3: 4, 5: 6};If you forget spaces between angle brackets, you will get a compilation error
// Compilation error!
cast<number<number>>(a);Always add spaces in nested casts!
// Perfectly fine (0.0 )
cast< number<number> >(a);Wyvern is a project made solely by Guilherme! My special thanks to you, you are awesome! π
I would also like to thank these people for making this little addition to it possible π
- Thanks JoeStrout for MiniScript!
- Thanks ayecue for Greybel-JS!
You all are simply the best! π₯°