A badly named, in-progress programming language just to learn how these things work. Wait, doesn't everyone write a compiler when they're bored?
Currently, the language is comparable to C, with some syntax changes inspired by Rust (that also make it a little easier to parse). The compiler outputs assembly code in yasm
format, so you will need yasm and a linker of your choice to compile it. The included Makefile and scripts use ld
. (Alternatively, you can use nasm
, but you will have to change the command being run in compiler/main.cup
and meta/bootstrap.sh
)
Only linux and macOS (only on x86_64) are supported.
For now, there's no support for looking at the PATH
, so it's a bin wonky. Make sure that you have the following tools (with the executables avialable in the correct places, or you might need to modify the paths manually in main/compiler.cup
):
yasm
: The assembler we are using.- On linux, the code expects to find this at
/usr/bin/yasm
. - On macOS, the code expects to find this at
/usr/local/bin/yasm
.
- On linux, the code expects to find this at
ld
: The linker we are using.- On both linux and macOS, the code expects to find this at
/usr/bin/ld
.
- On both linux and macOS, the code expects to find this at
The reference implementation of the compiler is written in CUP, so you'll need to use the pre-compiled YASM files to get the initial executable. You should be able to run the command below to create the ./build/cupcc
compiler:
$ ./meta/bootstrap.sh
Compile a program (and optionally run it) using:
$ ./build/cupcc /path/to/program.cup -o prog
$ ./prog 1 2 3 4
# OR
$ ./build/cupcc /path/to/program.cup -o prog -r 1 2 3 4
Make sure to not have the executable name end in .yasm
or .o
, since there are some temporary files created during compilation.
Some common functions you'll want are located in std/common.cup
import "std/common.cup";
fn main(arc: int, argv: char**): int {
putsln("Hello, world!");
return 0;
}
Variables are strongly typed. You can either declare them with a type, or they can be inferred if there is an initial assignment.
fn main() {
let x: int = 5; // Explicity define the type
let y = 6; // Infer the type
let z = x + y; // Add them, and infer the type
}
fn main() {
let x: int[10]; // An array of 10 ints (initializers not supported)
let y: int* = x; // Automatically decays to a pointer when passed or assigned
let z = y; // type(z) == int* also works
let a = x[0]; // Access the first element (`a` is an int)
let b = *(x+1); // Access the second element (can use pointer arithmetic)
}
// For now, enums just generate constant values with sequential numbers.
// They aren't a "type" on their own.
enum Type {
TypeInt,
TypeFloat,
TypeChar,
}
struct Variable {
typ: int; // Can't use `Type` here, because it's not a type
value: union { // Anonymous nested structures are allowed.
as_int: int;
as_char: char;
as_ptr: Variable*; // Can recursively define types.
};
};
fn main() {
let x: Variable; // No struct initializers yet
x.typ = TypeInt;
x.value.as_int = 5;
}
struct Value {
x: int;
};
method Value::inc(amount: int) {
// self (pointer) is implicitly passed in
self.x = self.x + amount;
}
method Value::print() {
print(self.x);
}
fn main() {
let v: Value;
let v_ptr = &v;
v.x = 0;
// Call methods using `::`
v::inc(10);
v_ptr::print(); // Also works for pointers
}
For now, the file I/O is very inspired by C, but it's wrapped using methods for the File
object. Optionally, you can use the raw syscalls (which behave like C), to deal with file descriptors manually. However it's preferred to use the File
object as it's more convenient and also provides buffered writes.
A simple implementation of cat
is:
import "std/file.cup";
fn main(argc: int, argv: char**) {
for (let i = 1; i < argc; ++i) {
let file = fopen(argv[i], 'r');
defer file::close(); // Close the file at the end of the block (in each iteration)
let buf: char[1024];
let n = file::read(buf, 1024); // use file-specific functions
while (n > 0) {
write(0, buf, n); // Use raw system calls
n = file::read(buf, 1024);
}
// file closed here because of defer
}
}
Want some more examples? Check out the examples directory, or the compiler directory, which contains the implementation of the compiler itself.
cup's People
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.