This commit is contained in:
Michael Zhang 2023-06-30 07:31:05 -05:00
commit cbce074ff1
14 changed files with 1412 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
.direnv

1006
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

18
Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "gust"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "gustc"
path = "src/main.rs"
[dependencies]
anyhow = "1.0.71"
chalk-engine = "0.91.0"
clap = { version = "4.3.9", features = ["derive"] }
lalrpop-util = { version = "0.20.0", features = ["lexer", "regex", "unicode"] }
redb = "1.0.1"
[build-dependencies]
lalrpop = "0.20.0"

3
build.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
lalrpop::process_root().unwrap();
}

12
default.nix Normal file
View File

@ -0,0 +1,12 @@
{ toolchain, makeRustPlatform, pkg-config }:
let rustPlatform = makeRustPlatform { inherit (toolchain) cargo rustc; };
in rustPlatform.buildRustPackage {
name = "liveterm";
src = ./.;
cargoLock.lockFile = ./Cargo.lock;
nativeBuildInputs = [ pkg-config ];
buildInputs = [ ];
}

5
examples/main.gs Normal file
View File

@ -0,0 +1,5 @@
from "std" import { fs::{self} };
fn main {
5
}

111
flake.lock Normal file
View File

@ -0,0 +1,111 @@
{
"nodes": {
"fenix": {
"inputs": {
"nixpkgs": "nixpkgs",
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1687501538,
"narHash": "sha256-6uxZWuSoM6rWDPo+7HLCBcNe8+4phnya4qJHS4IlbKo=",
"owner": "nix-community",
"repo": "fenix",
"rev": "3650022df24f0e5545502439ba7599b786455e2a",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1687171271,
"narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1687412861,
"narHash": "sha256-Z/g0wbL68C+mSGerYS2quv9FXQ1RRP082cAC0Bh4vcs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e603dc5f061ca1d8a19b3ede6a8cf9c9fcba6cdc",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1663551060,
"narHash": "sha256-e2SR4cVx9p7aW/XnVsGsWZBplApA9ZJUjc0fejJhnYo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8a5b9ee7b7a2b38267c9481f5c629c015108ab0d",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"fenix": "fenix",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_2"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1687460085,
"narHash": "sha256-Npfu+4+KpgtZd/JX9wUaV3qP8dwbmoRd4s1NSehwyiE=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "403433a35559962ad0df91c0ae85ab03e918ba54",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

34
flake.nix Normal file
View File

@ -0,0 +1,34 @@
{
inputs = { fenix.url = "github:nix-community/fenix"; };
outputs = { self, nixpkgs, flake-utils, fenix }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ fenix.overlays.default ];
};
toolchain = pkgs.fenix.default;
flakePkgs = rec { beng = pkgs.callPackage ./. { inherit toolchain; }; };
in rec {
packages = flake-utils.lib.flattenTree flakePkgs;
defaultPackage = packages.beng;
devShell = pkgs.mkShell {
inputsFrom = with packages; [ beng ];
packages = (with pkgs; [
cargo-watch
cargo-deny
cargo-edit
cargo-expand
pijul
# Get the nightly version of rustfmt so we can wrap comments
pkgs.fenix.default.rustfmt
]) ++ (with toolchain; [ cargo clippy rustc rustfmt ]);
};
});
}

3
rustfmt.toml Normal file
View File

@ -0,0 +1,3 @@
max_width = 80
tab_spaces = 2
wrap_comments = true

108
src/ast.rs Normal file
View File

@ -0,0 +1,108 @@
#[derive(Debug)]
pub struct Program {
pub(crate) items: Vec<Item>,
}
/// Range
#[derive(Debug)]
pub struct Loc(usize, usize);
impl Loc {
pub fn new(left: usize, right: usize) -> Self {
Loc(left, right)
}
}
// ===============================================
// Items
#[derive(Debug)]
pub struct Item {
pub(crate) kind: ItemKind,
pub(crate) loc: Loc,
}
#[derive(Debug)]
pub enum ItemKind {
FuncDef(FuncDef),
StructDef(StructDef),
}
// ===============================================
// Functions
#[derive(Debug)]
pub struct FuncDef {
pub(crate) name: Option<String>,
pub(crate) body: Expr,
pub(crate) loc: Loc,
}
// ===============================================
// Structs
#[derive(Debug)]
pub struct StructDef {
}
// ===============================================
// Expr
#[derive(Debug)]
pub struct Expr {
pub(crate) kind: ExprKind,
pub(crate) loc: Loc,
}
#[derive(Debug)]
pub enum ExprKind {
// Literals / primitives
Literal(Literal),
// More copmlex expressionsj
BinOp(Box<Expr>, BinOp, Box<Expr>),
Sequence(Sequence),
Paren(Box<Expr>),
}
#[derive(Debug)]
pub struct Sequence {
pub(crate) stmts: Vec<Stmt>,
pub(crate) inner: Box<Expr>,
}
// Stmts
#[derive(Debug)]
pub struct Stmt {
pub(crate) kind: StmtKind,
pub(crate) loc: Loc,
}
#[derive(Debug)]
pub enum StmtKind {
Expr(Expr),
}
// ===============================================
// Literals
#[derive(Debug)]
pub struct Literal {
pub(crate) kind: LiteralKind,
pub(crate) loc: Loc,
}
#[derive(Debug)]
pub enum LiteralKind {
Int(u64),
}
// ===============================================
// Random shit
#[derive(Debug)]
pub enum BinOp {
Plus,
}

67
src/grammar.lalrpop Normal file
View File

@ -0,0 +1,67 @@
use crate::ast::*;
grammar;
pub Program: Program = <items:Item*> => Program {
items,
};
Item: Item = {
<left:@L> <kind:ItemKind> <right:@R> =>
Item { kind, loc: Loc::new(left, right) },
};
ItemKind: ItemKind = {
"fn" <funcdef:FuncDef> => ItemKind::FuncDef(funcdef),
};
FuncDef: FuncDef =
<left:@L> <ident:Ident> <body:BlockExpr> <right:@R> => FuncDef {
name: Some(ident),
body,
loc: Loc::new(left, right),
};
Expr: Expr =
<left:@L> <kind:ExprKind> <right:@R> => Expr {
kind,
loc: Loc::new(left, right),
};
ExprKind: ExprKind = {
<literal:Literal> => ExprKind::Literal(literal),
"(" <expr:Expr> ")" => ExprKind::Paren(Box::new(expr)),
};
BlockExpr: Expr =
<left:@L> "{" <stmts:StmtSemi*> <expr:Expr> "}" <right:@R> => Expr {
kind: ExprKind::Sequence(Sequence {
stmts,
inner: Box::new(expr),
}),
loc: Loc::new(left, right),
};
StmtSemi: Stmt =
<left:@L> <kind:StmtKind> <right:@R> ";" => Stmt {
kind,
loc: Loc::new(left, right),
};
StmtKind: StmtKind = {
<expr:Expr> => StmtKind::Expr(expr),
};
Literal: Literal =
<left:@L> <kind:LiteralKind> <right:@R> => Literal {
kind,
loc: Loc::new(left, right),
};
LiteralKind: LiteralKind = {
r"[0-9]+" => LiteralKind::Int(<>.parse().unwrap()),
};
// Random shit
Ident: String = r"[A-Za-z_]+" => <>.to_owned();

38
src/main.rs Normal file
View File

@ -0,0 +1,38 @@
pub mod ast;
pub mod typeck;
use std::{path::PathBuf, fs::File, io::Read};
use clap::Parser;
use anyhow::Result;
use lalrpop_util::lalrpop_mod;
lalrpop_mod!(pub grammar);
#[derive(Debug, Parser)]
struct Opt {
input_file: PathBuf,
}
fn main() -> Result<()> {
let opt = Opt::parse();
let contents = {
let mut file = File::open(&opt.input_file)?;
let mut string = String::new();
file.read_to_string(&mut string)?;
string
};
let parser = grammar::ProgramParser::new();
let tree = parser.parse(&contents);
println!("tree: {tree:?}");
// TODO: Distill tree into rules
// TODO: Type-checking
Ok(())
}

4
src/typeck.rs Normal file
View File

@ -0,0 +1,4 @@
use crate::ast::Program;
pub fn check(ast: Program) {
}