peterd.net
me@peterd.net (720)371-7487 Github Resume Blog
mylang
mylang is an LLVM frontend I wrote that implements a C-like language, but it also adds tuples, destructuring, sum types, and some very basic pattern matching.
The source code is available here. It's written in Rust, which is a language produced by Mozilla as a replacement for C++.
Examples:
// Hello world fn printf(fmt: *i8, ...) -> i32; fn main(argc: i32, argv: **i8) -> i32 { printf("hello world\n"); return 0; }
// Parse compiler args fn printf(fmt: *i8, ...) -> i32; fn strcmp(x: *i8, y: *i8) -> i32; // Returns (filename, -h) fn parse_args(argc: i32, argv: **i8) -> (*i8, bool) { let file: *i8 = null; let help = false; for let i = 1; i < argc; i += 1 { let arg = argv[i]; if strcmp(arg, "-h") == 0 { help = true; continue; } file = arg; } return (file, help); } fn main(argc: i32, argv: **i8) -> i32 { let (file, help) = parse_args(argc, argv); printf("help = %d, file = %s\n", help, file); if help { printf("usage: mylangc [-h] <file>\n"); return 1; } if file == null { printf("missing file argument\n"); return 1; } return 0; }
// 4x4 Matrix multiplication fn printf(fmt: *i8, ...) -> i32; type mat4 = [4][4]f32; fn matmul(A: mat4, B: mat4) -> mat4 { let xx = A[0][0] * B[0][0] + A[0][1] * B[1][0] + A[0][2] * B[2][0] + A[0][3] * B[3][0]; let xy = A[0][0] * B[0][1] + A[0][1] * B[1][1] + A[0][2] * B[2][1] + A[0][3] * B[3][1]; let xz = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2] * B[2][2] + A[0][3] * B[3][2]; let xw = A[0][0] * B[0][3] + A[0][1] * B[1][3] + A[0][2] * B[2][3] + A[0][3] * B[3][3]; let yx = A[1][0] * B[0][0] + A[1][1] * B[1][0] + A[1][2] * B[2][0] + A[1][3] * B[3][0]; let yy = A[1][0] * B[0][1] + A[1][1] * B[1][1] + A[1][2] * B[2][1] + A[1][3] * B[3][1]; let yz = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2] * B[2][2] + A[1][3] * B[3][2]; let yw = A[1][0] * B[0][3] + A[1][1] * B[1][3] + A[1][2] * B[2][3] + A[1][3] * B[3][3]; let zx = A[2][0] * B[0][0] + A[2][1] * B[1][0] + A[2][2] * B[2][0] + A[2][3] * B[3][0]; let zy = A[2][0] * B[0][1] + A[2][1] * B[1][1] + A[2][2] * B[2][1] + A[2][3] * B[3][1]; let zz = A[2][0] * B[0][2] + A[2][1] * B[1][2] + A[2][2] * B[2][2] + A[2][3] * B[3][2]; let zw = A[2][0] * B[0][3] + A[2][1] * B[1][3] + A[2][2] * B[2][3] + A[2][3] * B[3][3]; let wx = A[3][0] * B[0][0] + A[3][1] * B[1][0] + A[3][2] * B[2][0] + A[3][3] * B[3][0]; let wy = A[3][0] * B[0][1] + A[3][1] * B[1][1] + A[3][2] * B[2][1] + A[3][3] * B[3][1]; let wz = A[3][0] * B[0][2] + A[3][1] * B[1][2] + A[3][2] * B[2][2] + A[3][3] * B[3][2]; let ww = A[3][0] * B[0][3] + A[3][1] * B[1][3] + A[3][2] * B[2][3] + A[3][3] * B[3][3]; return [[xx, xy, xz, xw], [yx, yy, yz, yw], [zx, zy, zz, zw], [wx, wy, wz, ww]]; } fn print(A: mat4) { for let i = 0; i < 4; i += 1 { for let j = 0; j < 4; j += 1 { printf("%10.4f ", A[i][j] as f64); } printf("\n"); } } fn main() -> i32 { let A = [[ 1.0, 9.0, 3.0, 4.0], [ 2.0, -4.0, 5.0, 0.5], [-3.0, 1.0, 6.0, -3.0], [ 6.0, 10.0, 11.0, 1.0]]; let B = matmul(A, A); print(A); print(B); return 0; }
// Structs and auto-deref fn printf(fmt: *i8, ...) -> i32; type vec3 struct { x: f32, y: f32, z: f32, } fn print(v: vec3) { let x = v.x as f64; let y = v.y as f64; let z = v.z as f64; printf("%f %f %f\n", x, y, z); } // Field accesses on pointers to structs are auto-deref'd. fn dot(x: *vec3, y: *vec3) -> f32 { return x.x * y.x + x.y * y.y + x.z * y.z; } fn main(argc: i32, argv: **i8) -> i32 { let a: vec3 = { x: 1.0, y: 2.0, z: 3.0, }; let b: vec3 = { x: 2.0, y: 3.0, z: 4.0, }; print(a); print(b); let ab = dot(&a, &b); printf("dot a, b = %f\n", ab as f64); return 0; }
// Pattern matching with `if let` fn printf(fmt: *i8, ...); type expr enum { int(i32), string(*i8), } fn print(e: expr) { if let int(i) = e { printf("%d\n", i); } if let string(s) = e { printf("%s\n", s); } } fn main() -> i32 { let e = expr.int(1); print(e); e = expr.string("hello world"); print(e); return 0; }