Files
vulcan/forge_core/src/ast.rs
T

243 lines
4.9 KiB
Rust
Raw Normal View History

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct Location {
pub line: usize,
pub col: usize
}
impl From<(usize, usize)> for Location {
fn from(value: (usize, usize)) -> Self {
Self { line: value.0, col: value.1 }
}
}
#[derive(PartialEq, Clone, Debug)]
pub struct Located<T> {
pub location: Location,
pub ast: T
}
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Program(pub Vec<Located<Declaration>>);
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
2023-07-03 23:11:44 -05:00
pub enum Declaration {
Function(Function),
Global(Global),
Const(Const),
2023-08-26 00:42:41 -05:00
Prototype(FunctionPrototype),
2023-07-03 23:11:44 -05:00
}
#[derive(PartialEq, Clone, Debug)]
2023-07-03 23:11:44 -05:00
pub struct Global {
pub name: String,
pub initial: Option<Expr>,
2023-07-03 23:11:44 -05:00
}
#[derive(PartialEq, Clone, Debug)]
2023-07-03 23:11:44 -05:00
pub struct Const {
pub name: String,
2023-08-02 21:56:26 -05:00
pub value: Option<Expr>,
2023-07-03 23:11:44 -05:00
pub string: Option<String>,
}
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Block(pub Vec<Located<Statement>>);
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
2023-07-03 23:11:44 -05:00
pub struct Function {
pub name: String,
2023-08-15 00:39:53 -05:00
pub args: Vec<String>,
2023-07-08 20:54:23 -05:00
pub body: Block,
2023-07-03 23:11:44 -05:00
}
2023-08-26 00:42:41 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct FunctionPrototype {
pub name: String,
pub args: Vec<String>,
}
2023-07-08 19:09:32 -05:00
#[derive(PartialEq, Clone, Debug)]
2023-07-04 02:49:29 -05:00
pub enum Statement {
Return(Return),
Assignment(Assignment),
2023-08-02 21:56:26 -05:00
Expr(Expr),
2023-07-04 02:49:29 -05:00
VarDecl(VarDecl),
Conditional(Conditional),
WhileLoop(WhileLoop),
RepeatLoop(RepeatLoop),
2023-08-15 01:30:35 -05:00
Asm(Asm)
2023-07-04 02:49:29 -05:00
}
2023-07-08 19:09:32 -05:00
#[derive(PartialEq, Clone, Debug)]
2023-08-02 21:56:26 -05:00
pub struct Return(pub Option<Expr>);
2023-07-04 02:49:29 -05:00
2023-07-08 19:09:32 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Assignment {
pub lvalue: Lvalue,
2023-08-14 00:26:02 -05:00
pub rvalue: Expr,
2023-07-08 19:09:32 -05:00
}
2023-07-04 02:49:29 -05:00
2023-08-13 23:55:49 -05:00
// An lvalue is just a tag on an expr. Any expr parses just fine as an lvalue... not all exprs
// will compile as lvalues. But this saves us essentially having to define the expr grammar twice:
// in the compiler we can tell whether it makes sense for a given lvalue to compile into code that
// yields an address or if it can only yield a value.
2023-07-08 19:09:32 -05:00
#[derive(PartialEq, Clone, Debug)]
2023-08-13 23:55:49 -05:00
pub struct Lvalue(pub BoxExpr);
2023-08-04 17:27:28 -05:00
impl From<&str> for Lvalue {
fn from(name: &str) -> Self {
2023-08-13 23:55:49 -05:00
Self(name.into())
2023-08-04 17:27:28 -05:00
}
}
impl From<String> for Lvalue {
fn from(name: String) -> Self {
2023-08-13 23:55:49 -05:00
Self(name.into())
}
}
impl From<Expr> for Lvalue {
fn from(value: Expr) -> Self {
Self(value.into())
2023-08-04 17:27:28 -05:00
}
2023-07-08 19:09:32 -05:00
}
#[derive(PartialEq, Clone, Debug)]
pub struct VarDecl {
pub name: String,
2023-08-14 00:26:02 -05:00
pub initial: Option<Expr>,
2023-07-08 19:09:32 -05:00
}
2023-07-04 02:49:29 -05:00
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Conditional {
2023-08-02 21:56:26 -05:00
pub condition: Expr,
2023-07-08 20:54:23 -05:00
pub body: Block,
pub alternative: Option<Block>,
}
2023-07-04 02:49:29 -05:00
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct WhileLoop {
2023-08-02 21:56:26 -05:00
pub condition: Expr,
2023-07-08 20:54:23 -05:00
pub body: Block,
}
2023-07-04 02:49:29 -05:00
2023-07-08 20:54:23 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct RepeatLoop {
2023-08-02 21:56:26 -05:00
pub count: Expr,
2023-07-08 20:54:23 -05:00
pub name: Option<String>,
pub body: Block,
}
2023-07-04 02:49:29 -05:00
2023-08-15 01:30:35 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Asm {
pub args: Vec<BoxExpr>,
pub body: String
}
2023-09-01 22:24:36 -05:00
#[derive(PartialEq, Clone, Debug)]
pub struct Call {
pub target: BoxExpr,
pub args: Vec<Expr>
}
2023-07-04 02:49:29 -05:00
/// One of the five arithmetical operators
2023-08-05 11:07:09 -05:00
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
2023-07-04 02:49:29 -05:00
pub enum Operator {
Add,
Sub,
Mul,
Div,
Mod,
2023-07-08 23:08:22 -05:00
And,
Or,
BitAnd,
BitOr,
Xor,
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
Lshift,
Rshift,
2023-07-04 02:49:29 -05:00
}
#[derive(Debug, PartialEq, Clone)]
pub enum Expr {
Number(i32),
Name(String),
2023-08-04 21:38:09 -05:00
Not(BoxExpr),
Neg(BoxExpr),
2023-08-13 18:58:47 -05:00
Deref(BoxExpr),
2023-08-04 21:38:09 -05:00
Address(Lvalue),
2023-09-01 22:24:36 -05:00
Call(Call),
New(BoxExpr),
2023-11-22 23:40:25 -06:00
Static(BoxExpr),
2023-08-05 11:07:09 -05:00
Subscript(BoxExpr, BoxExpr),
2023-08-04 21:38:09 -05:00
Infix(BoxExpr, Operator, BoxExpr),
2023-08-14 00:26:02 -05:00
String(String),
2023-07-04 02:49:29 -05:00
}
2023-07-05 23:19:54 -05:00
#[repr(transparent)]
#[derive(PartialEq, Clone, Debug)]
2023-08-02 21:56:26 -05:00
pub struct BoxExpr(pub Box<Expr>);
impl From<i32> for BoxExpr {
2023-07-05 23:19:54 -05:00
fn from(val: i32) -> Self {
2023-08-04 17:27:28 -05:00
BoxExpr(Box::from(Expr::Number(val)))
2023-07-05 23:19:54 -05:00
}
}
2023-08-02 21:56:26 -05:00
impl From<Expr> for BoxExpr {
fn from(expr: Expr) -> Self {
BoxExpr(Box::from(expr))
}
}
impl From<&str> for BoxExpr {
fn from(value: &str) -> Self {
2023-08-04 17:27:28 -05:00
Expr::Name(String::from(value)).into()
2023-07-05 23:19:54 -05:00
}
}
2023-08-13 23:55:49 -05:00
impl From<String> for BoxExpr {
fn from(value: String) -> Self {
Expr::Name(value).into()
}
}
2023-08-02 21:56:26 -05:00
impl From<BoxExpr> for Expr {
fn from(expr: BoxExpr) -> Self {
*(expr.0)
2023-07-05 23:19:54 -05:00
}
}
2023-08-02 21:56:26 -05:00
impl From<i32> for Expr {
fn from(value: i32) -> Self {
2023-08-04 17:27:28 -05:00
Self::Number(value)
2023-08-02 21:56:26 -05:00
}
}
impl From<&str> for Expr {
fn from(value: &str) -> Self {
2023-08-04 17:27:28 -05:00
Self::Name(String::from(value))
}
}
2024-05-03 21:04:57 -05:00
impl Statement {
pub fn description(&self) -> String {
String::from(
match self {
Statement::Return(_) => "return",
Statement::Assignment(_) => "assignment",
Statement::Expr(_) => "expr",
Statement::VarDecl(_) => "varDecl",
Statement::Conditional(_) => "conditional",
Statement::WhileLoop(_) => "whileLoop",
Statement::RepeatLoop(_) => "repeatLoop",
Statement::Asm(_) => "asm"
}
)
}
}