work
This commit is contained in:
@@ -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
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
pub struct Module {}
|
||||
mod namespace;
|
||||
pub use namespace::*;
|
||||
|
||||
use super::Id;
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ def_tokens! {
|
||||
}
|
||||
keyword {
|
||||
Let: "let",
|
||||
Do: "do",
|
||||
Import: "import",
|
||||
Fn: "fn",
|
||||
If: "if",
|
||||
Loop: "loop",
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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() {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fn thing() {
|
||||
print("hello from other");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user