This commit is contained in:
2026-04-18 00:16:03 -04:00
parent b3f77076d4
commit d864adfd05
12 changed files with 167 additions and 38 deletions
+54
View File
@@ -0,0 +1,54 @@
use std::ops::{Index, IndexMut};
pub struct Id<T> {
idx: usize,
_pd: std::marker::PhantomData<T>,
}
pub struct IdVec<T> {
vec: Vec<T>,
}
impl<T> IdVec<T> {
pub fn add(&mut self, val: T) -> Id<T> {
let id = Id {
idx: self.vec.len(),
_pd: Default::default(),
};
self.vec.push(val);
id
}
}
impl<T> Index<Id<T>> for IdVec<T> {
type Output = T;
fn index(&self, index: Id<T>) -> &Self::Output {
&self.vec[index.idx]
}
}
impl<T> IndexMut<Id<T>> for IdVec<T> {
fn index_mut(&mut self, index: Id<T>) -> &mut Self::Output {
&mut self.vec[index.idx]
}
}
impl<T> Default for IdVec<T> {
fn default() -> Self {
Self {
vec: Default::default(),
}
}
}
impl<T> Clone for Id<T> {
fn clone(&self) -> Self {
Self {
idx: self.idx.clone(),
_pd: self._pd.clone(),
}
}
}
impl<T> Copy for Id<T> {}
+20 -1
View File
@@ -1,4 +1,23 @@
mod id;
mod structs;
pub use id::*;
pub use structs::*;
pub struct Ir {}
pub struct Ir {
pub root: Id<Namespace>,
pub namespaces: IdVec<Namespace>,
}
impl Ir {
pub fn root(&mut self) -> &mut Namespace {
&mut self.namespaces[self.root]
}
}
impl Default for Ir {
fn default() -> Self {
let mut namespaces = IdVec::default();
let root = namespaces.add(Namespace::default());
Self { root, namespaces }
}
}
+4 -1
View File
@@ -1 +1,4 @@
pub struct Module {}
mod namespace;
pub use namespace::*;
use super::Id;
+17
View File
@@ -0,0 +1,17 @@
use super::*;
use crate::parser::Ident;
use std::collections::HashMap;
#[derive(Default)]
pub struct Namespace {
pub items: HashMap<Ident, Item>,
}
pub enum Item {
Import(Id<Namespace>),
}
// issue: if I try to parse a function body, I'll want to have clear statements such as
// "call trait fn func on x" or "call field func of x", but you (often) can't tell until typed
// x.func
// x'func
+4 -8
View File
@@ -1,11 +1,13 @@
use crate::{
io::CompilerOutput,
parser::{Node, parse_root},
parser::{Node, parse_file},
parser_ir::parse_program,
};
mod io;
mod ir;
mod parser;
mod parser_ir;
fn main() {
let mut args = std::env::args();
@@ -14,15 +16,9 @@ fn main() {
return;
};
let mut output = CompilerOutput::new();
let root = parse_root(&path, &mut output);
let root = parse_file(&path, &mut output);
if let Some(root) = root {
print!("{}", root.new_dsp());
// for item in &root.items {
// output.errors.push(io::CompilerMsg {
// spans: vec![item.span],
// msg: format!("hello"),
// });
// }
}
output.write(&mut std::io::stdout());
}
+1 -1
View File
@@ -31,7 +31,7 @@ def_tokens! {
}
keyword {
Let: "let",
Do: "do",
Import: "import",
Fn: "fn",
If: "if",
Loop: "loop",
+22
View File
@@ -5,3 +5,25 @@ mod nodes;
use cursor::*;
pub use node::*;
pub use nodes::*;
use crate::io::CompilerOutput;
pub fn parse_file(path: &str, output: &mut CompilerOutput) -> Option<Body> {
let code = match std::fs::read_to_string(path) {
Ok(code) => code,
Err(err) => {
output.error(format!("Failed to read input file: {err}"));
return None;
}
};
output.files.push(path.to_string());
let mut ctx = ParseCtx::new(Cursor::new(&code, 0));
let root = match ctx.parse() {
Ok(v) => v,
Err(msg) => {
output.error(msg);
return None;
}
};
Some(root)
}
+2 -25
View File
@@ -1,13 +1,10 @@
use crate::{
io::{CompilerMsg, CompilerOutput},
parser::{Cursor, nodes::*},
};
mod ctx;
mod dsp;
pub use ctx::*;
pub use dsp::*;
use crate::io::CompilerMsg;
pub trait Node: Sized {
fn parse(ctx: &mut ParseCtx) -> Result<Self, CompilerMsg>;
fn fmt(&self, f: &mut std::fmt::Formatter, ctx: DisplayCtx) -> std::fmt::Result;
@@ -18,23 +15,3 @@ pub trait Node: Sized {
self.dsp(DisplayCtx { indent: 0 })
}
}
pub fn parse_root(path: &str, output: &mut CompilerOutput) -> Option<Body> {
let root_code = match std::fs::read_to_string(path) {
Ok(code) => code,
Err(err) => {
output.error(format!("Failed to read input file: {err}"));
return None;
}
};
output.files.push(path.to_string());
let mut ctx = ParseCtx::new(Cursor::new(&root_code, 0));
let root = match ctx.parse() {
Ok(v) => v,
Err(msg) => {
output.error(msg);
return None;
}
};
Some(root)
}
+15 -1
View File
@@ -11,12 +11,18 @@ pub enum ItemTy {
ty: Option<Type>,
val: Expr,
},
Fn(Func),
Expr(Expr),
Import(Ident),
}
impl Node for Item {
fn parse(ctx: &mut ParseCtx) -> Result<Self, CompilerMsg> {
let ty = match ctx.expect_peek()? {
Token::Fn => {
ctx.next();
ItemTy::Fn(ctx.parse()?)
}
Token::Let => {
ctx.next();
let name = ctx.parse()?;
@@ -28,6 +34,10 @@ impl Node for Item {
let val = ctx.parse()?;
ItemTy::Let { name, ty, val }
}
Token::Import => {
ctx.next();
ItemTy::Import(ctx.parse()?)
}
_ => ItemTy::Expr(ctx.parse()?),
};
Ok(Self {
@@ -38,6 +48,7 @@ impl Node for Item {
fn fmt(&self, f: &mut std::fmt::Formatter, ctx: DisplayCtx) -> std::fmt::Result {
match &self.ty {
ItemTy::Fn(func) => func.fmt(f, ctx)?,
ItemTy::Let { name, ty, val } => {
write!(f, "let {}", name.dsp(ctx))?;
if let Some(ty) = ty {
@@ -45,7 +56,8 @@ impl Node for Item {
}
write!(f, " = {}", val.dsp(ctx))?;
}
ItemTy::Expr(id) => id.fmt(f, ctx)?,
ItemTy::Expr(expr) => expr.fmt(f, ctx)?,
ItemTy::Import(ident) => write!(f, "import {}", ident.dsp(ctx))?,
}
Ok(())
}
@@ -56,6 +68,8 @@ impl Item {
match &self.ty {
ItemTy::Let { val, .. } => val.ends_with_block(),
ItemTy::Expr(id) => id.ends_with_block(),
ItemTy::Fn(f) => f.ends_with_block(),
ItemTy::Import(ident) => false,
}
}
pub fn needs_semicolon(&self) -> bool {
+23
View File
@@ -0,0 +1,23 @@
use crate::{
io::CompilerOutput,
ir::{Ir, Namespace},
parser::{self, parse_file},
};
pub fn parse_program(path: &str, output: &mut CompilerOutput) -> Option<Ir> {
let root = parse_file(path, output)?;
let mut ir = Ir::default();
add_defs(ir.root(), &root);
Some(ir)
}
pub fn add_defs(namespace: &mut Namespace, body: &parser::Body) {
for item in &body.items {
match &item.ty {
parser::ItemTy::Let { name, ty, val } => todo!(),
parser::ItemTy::Fn(func) => todo!(),
parser::ItemTy::Expr(expr) => todo!(),
parser::ItemTy::Import(ident) => todo!(),
}
}
}
+2 -1
View File
@@ -1,3 +1,5 @@
modl other;
let x: i32 = 3;
while true {
print("hello");
@@ -9,5 +11,4 @@ let y = true;
if y => print("hello");
fn thing() {
}
+3
View File
@@ -0,0 +1,3 @@
fn thing() {
print("hello from other");
}