IR generation is (almost) done!!!
This commit is contained in:
parent
250d40dab7
commit
9ddbf38ecb
|
@ -1,18 +1,6 @@
|
|||
MyType: Type
|
||||
MyType = type
|
||||
Variant1
|
||||
| Variant2 (int 0..usize)
|
||||
| Variant3 str (int 0..21)
|
||||
main: Int
|
||||
main = 1 + (if (distance_squared 10 2) > 10 then 1000 else 2000)
|
||||
|
||||
myFunc: str, int -> MyType
|
||||
myFunc strval intval =
|
||||
if intval < 21 && intval > 0
|
||||
then Variant3 strval intval
|
||||
else Variant1
|
||||
|
||||
ComplexType: Type
|
||||
ComplexType = type
|
||||
ComplexVariant (str, int -> MyType) str
|
||||
|
||||
myVal : ComplexType
|
||||
myVal = ComplexVariant myFunc "uwu~"
|
||||
distance_squared: Int, Int -> Int
|
||||
distance_squared a b = a * a + b * b
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
use core::fmt;
|
||||
use std::{collections::LinkedList, mem};
|
||||
|
||||
use super::{value::Value, pattern::Pattern, Identifier};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Expr {
|
||||
pub identifier: Identifier,
|
||||
pub operation: Operation,
|
||||
pub formals: Vec<Identifier>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Operation::NoOp = self.operation {
|
||||
self.identifier.fmt(f)
|
||||
} else {
|
||||
write!(f,
|
||||
"{} = {:?}{}",
|
||||
self.identifier,
|
||||
self.operation,
|
||||
self.formals.iter()
|
||||
.map(|f| format!(" {f}"))
|
||||
.collect::<String>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Operation {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Range,
|
||||
Eq,
|
||||
NEq,
|
||||
LessThan,
|
||||
GreaterThan,
|
||||
LAnd,
|
||||
LOr,
|
||||
Const(Value),
|
||||
Call,
|
||||
VariantUnion,
|
||||
FunctionType,
|
||||
NoOp,
|
||||
Conditional(Vec<(Pattern, LinkedList<Expr>)>),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Operation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
Self::Add => "plus",
|
||||
Self::Sub => "minus",
|
||||
Self::Mul => "times",
|
||||
Self::Div => "div",
|
||||
Self::Mod => "mod",
|
||||
Self::Range => "to",
|
||||
Self::Eq => "equals",
|
||||
Self::NEq => "nequals",
|
||||
Self::LessThan => "lessthan",
|
||||
Self::GreaterThan => "morethan",
|
||||
Self::LAnd => "and",
|
||||
Self::LOr => "or",
|
||||
Self::Const(v) => {
|
||||
return write!(f, "const[{v:?}]");
|
||||
},
|
||||
Self::Call => "call",
|
||||
Self::VariantUnion => "orvariant",
|
||||
Self::FunctionType => "yields",
|
||||
Self::NoOp => "noop",
|
||||
Self::Conditional(branches) => {
|
||||
return write!(f, "cond({branches:?})");
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_last_ident_name(mut exprs: LinkedList<Expr>, name: String) -> LinkedList<Expr> {
|
||||
if let Some(expr) = exprs.back_mut() {
|
||||
let mut placeholder = Identifier::ROOT;
|
||||
mem::swap(&mut expr.identifier, &mut placeholder);
|
||||
placeholder = placeholder.set_name(name);
|
||||
mem::swap(&mut expr.identifier, &mut placeholder);
|
||||
}
|
||||
exprs
|
||||
}
|
||||
|
||||
pub fn get_last_ident(exprs: &LinkedList<Expr>) -> Option<Identifier> {
|
||||
exprs.back().map(|expr| expr.identifier.clone())
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
use core::fmt;
|
||||
|
||||
use crate::cons;
|
||||
|
||||
use self::{types::Type, value::Value};
|
||||
|
||||
pub mod types;
|
||||
pub mod expr;
|
||||
pub mod value;
|
||||
pub mod pattern;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
// name id depth
|
||||
pub struct Identifier(pub String, usize, usize);
|
||||
|
||||
impl Identifier {
|
||||
pub const ROOT: Identifier = Identifier(String::new(), 1, 0);
|
||||
|
||||
pub fn subid_with_name(&self, new_name: String, index: u32) -> Identifier {
|
||||
Identifier (
|
||||
new_name,
|
||||
self.1 * nth_prime(self.2).pow(index + 1),
|
||||
self.2 + 1
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subid_generate_name(&self, short_name: &str, index: u32) -> Identifier {
|
||||
self.subid_with_name(format!("{}.{short_name}", self.0), index)
|
||||
}
|
||||
|
||||
pub fn matches(&self, name: &str) -> bool {
|
||||
name == self.0.as_str()
|
||||
}
|
||||
|
||||
pub fn set_name(self, new_name: String) -> Identifier {
|
||||
Identifier(new_name, self.1, self.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}.{}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum IrError {
|
||||
MismatchedNames(String, String),
|
||||
Undefined(String),
|
||||
MissingExpression,
|
||||
NestedTypeDeclarations,
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, IrError>;
|
||||
|
||||
// note: the 0th prime is 2
|
||||
pub fn nth_prime(n: usize) -> usize {
|
||||
nth_prime_from(n, 3, vec![2])
|
||||
}
|
||||
|
||||
pub fn nth_prime_from(n: usize, i: usize, known_primes: Vec<usize>) -> usize {
|
||||
if is_prime(i, &known_primes) {
|
||||
if known_primes.len() > n {
|
||||
*known_primes.last().unwrap()
|
||||
} else {
|
||||
nth_prime_from(n, i + 2, cons(known_primes, i))
|
||||
}
|
||||
} else {
|
||||
nth_prime_from(n, i + 2, known_primes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_prime(x: usize, known_primes: &[usize]) -> bool {
|
||||
!known_primes.iter()
|
||||
.take_while(|p| **p * **p < x)
|
||||
.any(|p| x % *p == 0)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Declaration {
|
||||
pub identifier: Identifier,
|
||||
pub value_type: Type,
|
||||
pub value: Value,
|
||||
}
|
||||
|
||||
impl fmt::Display for Declaration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f,
|
||||
"{0} is of type {1} and has value\n{2}",
|
||||
self.identifier,
|
||||
self.value_type,
|
||||
self.value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BindingScope<'a>(Option<&'a BindingScope<'a>>, Vec<Identifier>);
|
||||
|
||||
impl<'a> BindingScope<'a> {
|
||||
pub const ROOT: BindingScope<'static> = BindingScope(None, Vec::new());
|
||||
|
||||
pub fn bind(&self, idents: Vec<Identifier>) -> BindingScope {
|
||||
BindingScope(Some(self), idents)
|
||||
}
|
||||
|
||||
pub fn bind_single(self, ident: Identifier) -> BindingScope<'a> {
|
||||
BindingScope(self.0, cons(self.1, ident))
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &str) -> Option<&Identifier> {
|
||||
let BindingScope(next_scope, identifiers) = self;
|
||||
identifiers.iter()
|
||||
.find(|ident| ident.matches(name))
|
||||
.or_else(|| next_scope.and_then(|s| s.lookup(name)))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
use crate::token::Literal;
|
||||
|
||||
use super::Identifier;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Pattern {
|
||||
Literal(Literal),
|
||||
Binding(Identifier),
|
||||
Variant(Identifier, Vec<Pattern>),
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use core::fmt;
|
||||
|
||||
use super::Identifier;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Variant {
|
||||
pub name: Identifier,
|
||||
pub elements: Vec<Type>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Variant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f,
|
||||
"{} {}",
|
||||
self.name,
|
||||
self.elements.iter()
|
||||
.map(|e| e.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Type {
|
||||
UserDefined(Vec<Variant>),
|
||||
Function(Vec<Type>, Box<Type>),
|
||||
Primitive(PrimitiveType),
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::UserDefined(variants) =>
|
||||
f.write_str(
|
||||
variants.into_iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
.join(" | ")
|
||||
.as_str()
|
||||
),
|
||||
Self::Function(args, return_type) =>
|
||||
write!(f,
|
||||
"{} -> {}",
|
||||
args.into_iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
.join(" , "),
|
||||
return_type
|
||||
),
|
||||
Self::Primitive(p) => p.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PrimitiveType {
|
||||
Int,
|
||||
Str,
|
||||
Type,
|
||||
}
|
||||
|
||||
impl fmt::Display for PrimitiveType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(
|
||||
match self {
|
||||
Self::Int => "int",
|
||||
Self::Str => "str",
|
||||
Self::Type => "Type",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
use core::fmt;
|
||||
use std::collections::LinkedList;
|
||||
|
||||
use super::{expr::Expr, Identifier};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Value {
|
||||
Int(usize),
|
||||
String(String),
|
||||
Function(Vec<Identifier>, LinkedList<Expr>),
|
||||
Structural(usize, Vec<Value>),
|
||||
}
|
||||
|
||||
impl fmt::Display for Value {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Int(v) => write!(f, "{}", v),
|
||||
Self::String(val) => write!(f, "\"{val}\""),
|
||||
Self::Function(args, exprs) => write!(f,
|
||||
"function({}):{}",
|
||||
args.into_iter()
|
||||
.map(|a| a.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
exprs.into_iter()
|
||||
.map(|e| format!("\n\t{e}"))
|
||||
.collect::<String>(),
|
||||
),
|
||||
Self::Structural(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
20
src/main.rs
20
src/main.rs
|
@ -28,9 +28,22 @@ fn main() -> std::io::Result<()> {
|
|||
};
|
||||
|
||||
println!("Parse successful!!");
|
||||
for decl in program.0 {
|
||||
for decl in &program.0 {
|
||||
println!("{decl:?}\n");
|
||||
}
|
||||
|
||||
println!("Building IR...");
|
||||
match program.gen_ir() {
|
||||
Ok(program) =>
|
||||
println!(
|
||||
"IR built successfully!\n{}",
|
||||
program.into_iter()
|
||||
.map(|decl| format!("\n\n{decl}"))
|
||||
.collect::<String>(),
|
||||
),
|
||||
Err(e) =>
|
||||
println!("Oh noes! {e:?}"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -48,3 +61,8 @@ pub fn join<T>(mut a: LinkedList<T>, mut b: LinkedList<T>) -> LinkedList<T> {
|
|||
a.append(&mut b);
|
||||
a
|
||||
}
|
||||
|
||||
pub fn join_vec<T>(mut a: Vec<T>, mut b: Vec<T>) -> Vec<T> {
|
||||
a.append(&mut b);
|
||||
a
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::mem::{Discriminant, discriminant};
|
||||
|
||||
use crate::token::Token;
|
||||
use crate::{token::Token, ir::{self, IrError, Identifier, BindingScope, types::{Type, PrimitiveType}}};
|
||||
|
||||
use super::{Parsable, WrappedLexer, ParseError, absorb_token_or_error, expr::Expr};
|
||||
|
||||
|
@ -48,3 +48,32 @@ impl Parsable for Declaration {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Declaration {
|
||||
pub fn gen_ir(self, bindings: &BindingScope, index: u32, parent_id: Identifier) -> Result<Option<ir::Declaration>, IrError> {
|
||||
let Declaration { name, type_, name2, args, value } = self;
|
||||
if name != name2 {
|
||||
Err(IrError::MismatchedNames(name, name2))
|
||||
} else {
|
||||
let own_id = parent_id.subid_with_name(name, index);
|
||||
let args = args.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, variable_name)| own_id.subid_with_name(variable_name, i as u32))
|
||||
.collect::<Vec<_>>();
|
||||
let n_args = args.len() as u32;
|
||||
let local_binding = bindings.bind(args.clone());
|
||||
let expression_dag = value.gen_ir(&local_binding, &own_id, n_args, false)?;
|
||||
Ok(Some(
|
||||
ir::Declaration {
|
||||
identifier: own_id,
|
||||
value_type: Type::Primitive(PrimitiveType::Int), // TODO
|
||||
value: ir::value::Value::Function(args, expression_dag),
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_identifier(&self, parent: &Identifier, index: u32) -> Option<Identifier> {
|
||||
Some(parent.subid_with_name(self.name.clone(), index))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
//
|
||||
// <case> ::= <binding_pattern> Aro <expr>
|
||||
|
||||
use std::mem::{Discriminant, discriminant};
|
||||
use std::{mem::{Discriminant, discriminant}, collections::LinkedList};
|
||||
|
||||
use crate::token::{Literal, Token};
|
||||
use crate::{token::{Literal, Token}, ir::{self, Identifier, expr::{Operation, set_last_ident_name}, BindingScope, pattern::Pattern, IrError}, cons_ll, join};
|
||||
|
||||
use super::{Parsable, pattern::BindingPattern, infix::Rank1Exp, ParseError, WrappedLexer, absorb_token_or_error, parse_delineated_vec};
|
||||
use super::{Parsable, pattern::BindingPattern, infix::{Rank1Exp, GenIR}, ParseError, WrappedLexer, absorb_token_or_error, parse_delineated_vec};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expr {
|
||||
|
@ -73,6 +73,90 @@ impl Parsable for Expr {
|
|||
}
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
pub fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
match self {
|
||||
Self::If(cond, if_block) => {
|
||||
let self_ident = parent.subid_generate_name("ifblk", index);
|
||||
let preceding_expressions = cond.gen_ir(bindings, &self_ident, 0, type_context)?;
|
||||
let conditional = Operation::Conditional(match *if_block {
|
||||
IfBlock::IfIs(case, more_cases) => {
|
||||
Some(case).into_iter()
|
||||
.chain(more_cases)
|
||||
.enumerate()
|
||||
.map(|(i, Case(pattern, expr))| {
|
||||
let (pattern_bindings, pattern) = pattern.gen_ir(bindings, &self_ident, 2 * i as u32)?;
|
||||
let new_scope = bindings.bind(pattern_bindings);
|
||||
let new_exprs = expr.gen_ir(&new_scope, &self_ident, 2*i as u32 + 1, type_context)?;
|
||||
Ok((pattern, new_exprs))
|
||||
})
|
||||
.collect::<ir::Result<Vec<_>>>()
|
||||
}
|
||||
IfBlock::IfThen(positive, negative) => {
|
||||
vec![negative, positive]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(v, expr)|
|
||||
expr.gen_ir(bindings, &self_ident, v as u32, type_context).map(|expr|
|
||||
(Pattern::Literal(Literal::Int(v as u64)), expr)
|
||||
)
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
}?);
|
||||
let new_expr = ir::expr::Expr {
|
||||
identifier: self_ident,
|
||||
operation: conditional,
|
||||
formals: vec![preceding_expressions.back()
|
||||
.ok_or(IrError::MissingExpression)?
|
||||
.identifier
|
||||
.clone()]
|
||||
};
|
||||
Ok(cons_ll(preceding_expressions, new_expr))
|
||||
}
|
||||
Self::Let(first_let, more_lets, finally) => {
|
||||
let self_ident = parent.subid_generate_name("letmany", index);
|
||||
let n_lets = more_lets.len() + 1;
|
||||
let (bindings, prior_exprs) = [*first_let].into_iter()
|
||||
.chain(more_lets)
|
||||
.enumerate()
|
||||
.try_fold(
|
||||
(bindings.bind(Vec::with_capacity(n_lets)), LinkedList::new()),
|
||||
|(bindings, exprs), (i, LetStmt(name, parsetree))| {
|
||||
let new_exprs = set_last_ident_name(
|
||||
parsetree.gen_ir(&bindings, &self_ident, i as u32, type_context)?,
|
||||
name
|
||||
);
|
||||
let new_bindings = bindings.bind_single(
|
||||
new_exprs.back()
|
||||
.ok_or(IrError::MissingExpression)?
|
||||
.identifier
|
||||
.clone()
|
||||
);
|
||||
Ok((new_bindings, join(exprs, new_exprs)))
|
||||
}
|
||||
)?;
|
||||
let exprs = finally.gen_ir(&bindings, &self_ident, n_lets as u32, type_context)?;
|
||||
Ok(join(prior_exprs, exprs))
|
||||
}
|
||||
Self::Infix(infix) => infix.gen_ir(bindings, parent, index, type_context),
|
||||
Self::Type(expr) =>
|
||||
if type_context {
|
||||
Err(IrError::NestedTypeDeclarations)
|
||||
} else {
|
||||
expr.gen_ir(bindings, parent, index, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo: refactor this to infix
|
||||
#[derive(Debug)]
|
||||
pub enum TightExpr {
|
||||
Literal(Literal),
|
||||
|
|
|
@ -1,11 +1,228 @@
|
|||
use crate::token::{InfixRank1, InfixRank2, InfixRank3, InfixRank5, InfixRank6, InfixRank7};
|
||||
use std::collections::LinkedList;
|
||||
|
||||
use crate::{token::{InfixRank1, InfixRank2, InfixRank3, InfixRank5, InfixRank6, Literal, InfixRank4}, ir::{BindingScope, Identifier, self, expr::{get_last_ident, Operation, Expr}, IrError, value::Value}, join, cons_ll, cons};
|
||||
|
||||
use super::expr::TightExpr;
|
||||
|
||||
pub type Rank1Exp = (Rank2Exp, Vec<(InfixRank1, Rank2Exp)>);
|
||||
pub type Rank2Exp = (Rank3Exp, Vec<(InfixRank2, Rank3Exp)>);
|
||||
pub type Rank3Exp = (Rank4Exp, Vec<(InfixRank3, Rank4Exp)>);
|
||||
pub type Rank4Exp = (Rank5Exp, Vec< Rank5Exp>);
|
||||
pub type Rank4Exp = (Rank5Exp, Vec<(InfixRank4, Rank5Exp)>);
|
||||
pub type Rank5Exp = (Rank6Exp, Vec<(InfixRank5, Rank6Exp)>);
|
||||
pub type Rank6Exp = (Rank7Exp, Vec<(InfixRank6, Rank7Exp)>);
|
||||
pub type Rank7Exp = (Box<TightExpr>, Vec<(InfixRank7, TightExpr)>);
|
||||
pub type Rank7Exp = (Box<TightExpr>, Vec< TightExpr>);
|
||||
|
||||
pub trait GenIR {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>>;
|
||||
}
|
||||
|
||||
pub trait InfixOp {
|
||||
fn gen_ir(&self) -> Operation;
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank1 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
match self {
|
||||
Self::LOr => Operation::LOr,
|
||||
Self::VBar => Operation::VariantUnion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank2 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
match self {
|
||||
Self::LAnd => Operation::LAnd,
|
||||
Self::Aro => Operation::FunctionType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank3 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
match self {
|
||||
Self::Eq => Operation::Eq,
|
||||
Self::NEq => Operation::NEq,
|
||||
Self::LessThan => Operation::LessThan,
|
||||
Self::GreaterThan => Operation::GreaterThan,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank4 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
Operation::Range
|
||||
}
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank5 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
match self {
|
||||
Self::Add => Operation::Add,
|
||||
Self::Sub => Operation::Sub,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfixOp for InfixRank6 {
|
||||
fn gen_ir(&self) -> Operation {
|
||||
match self {
|
||||
Self::Mul => Operation::Mul,
|
||||
Self::Mod => Operation::Mod,
|
||||
Self::Div => Operation::Div,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<NextRank: GenIR, NextRank2: GenIR, Op: InfixOp> GenIR for (NextRank, Vec<(Op, NextRank2)>) {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
let (first_arg, ops) = self;
|
||||
if !ops.is_empty() {
|
||||
let ident = parent.subid_with_name(String::new(), index);
|
||||
let prior_expressions = first_arg.gen_ir(bindings, &ident, 0, type_context)?;
|
||||
(prior_expressions, ops).gen_ir(bindings, &ident, 1, type_context)
|
||||
} else {
|
||||
first_arg.gen_ir(bindings, parent, index, type_context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<NextRank: GenIR, Op: InfixOp> GenIR for (LinkedList<Expr>, Vec<(Op, NextRank)>) {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
let (first_arg_exprs, mut ops) = self;
|
||||
if let Some((this_op, second_arg)) = ops.pop() {
|
||||
let this_ident = parent.subid_with_name(String::new(), index);
|
||||
let second_arg_exprs = second_arg.gen_ir(bindings, parent, index + 1, type_context)?;
|
||||
let op = this_op.gen_ir();
|
||||
let first_arg_ident = get_last_ident(&first_arg_exprs).ok_or(IrError::MissingExpression)?;
|
||||
let second_arg_ident = get_last_ident(&second_arg_exprs).ok_or(IrError::MissingExpression)?;
|
||||
let first_arg_name = &first_arg_ident.0;
|
||||
let second_arg_name = &second_arg_ident.0;
|
||||
let final_name = format!("{first_arg_name}-{op:?}-{second_arg_name}");
|
||||
let this_ident = this_ident.set_name(final_name);
|
||||
let new_expr = ir::expr::Expr {
|
||||
identifier: this_ident,
|
||||
operation: op,
|
||||
formals: vec![first_arg_ident, second_arg_ident],
|
||||
};
|
||||
let all_prior_exprs = join(first_arg_exprs, second_arg_exprs);
|
||||
let all_exprs = cons_ll(all_prior_exprs, new_expr);
|
||||
(all_exprs, ops).gen_ir(bindings, parent, index + 2, type_context)
|
||||
} else {
|
||||
Ok(first_arg_exprs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//pub type Rank4Exp = (TightExpr, Vec<Rank5Exp>);
|
||||
impl GenIR for Rank7Exp {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
let (thing_to_be_called, arguments) = self;
|
||||
if arguments.is_empty() {
|
||||
thing_to_be_called.gen_ir(bindings, parent, index, type_context)
|
||||
} else {
|
||||
let this_ident = parent.subid_with_name(String::new() /*will replace*/, index);
|
||||
let n_args = arguments.len() + 1;
|
||||
let (arg_idents, prior_exprs) = Some(*thing_to_be_called)
|
||||
.into_iter()
|
||||
.chain(arguments)
|
||||
.enumerate()
|
||||
.map(|(i, arg)| arg.gen_ir(bindings, &this_ident, i as u32, type_context))
|
||||
.try_fold(
|
||||
(Vec::with_capacity(n_args), LinkedList::new()),
|
||||
|(idents, exprs), new_exprs|
|
||||
new_exprs.and_then(|new_exprs2|
|
||||
Ok((
|
||||
cons(
|
||||
idents,
|
||||
get_last_ident(&new_exprs2).ok_or(IrError::MissingExpression)?
|
||||
),
|
||||
join(exprs, new_exprs2)
|
||||
))
|
||||
)
|
||||
)?;
|
||||
let call_ident_name = &arg_idents.get(0).ok_or(IrError::MissingExpression)?.0;
|
||||
let new_ident_name = format!("{call_ident_name}_result");
|
||||
let new_expr = ir::expr::Expr {
|
||||
identifier: this_ident.set_name(new_ident_name),
|
||||
operation: Operation::Call,
|
||||
formals: arg_idents,
|
||||
};
|
||||
Ok(cons_ll(prior_exprs, new_expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenIR for TightExpr {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
match self {
|
||||
TightExpr::Literal(l) => {
|
||||
let value = match l {
|
||||
Literal::String(s) => Value::String(s),
|
||||
Literal::Int(i) => Value::Int(i as usize),
|
||||
};
|
||||
let expr = ir::expr::Expr {
|
||||
identifier: parent.subid_with_name(format!("literal"), index),
|
||||
operation: Operation::Const(value),
|
||||
formals: Vec::new(),
|
||||
};
|
||||
Ok(LinkedList::from([expr]))
|
||||
},
|
||||
TightExpr::Grouped(e) => e.gen_ir(bindings, parent, index, type_context),
|
||||
TightExpr::Symbol(s) =>
|
||||
if let Some(ident) = bindings.lookup(&s) {
|
||||
Ok(LinkedList::from([Expr {
|
||||
identifier: ident.clone(),
|
||||
operation: Operation::NoOp,
|
||||
formals: Vec::new(),
|
||||
}]))
|
||||
} else if type_context {
|
||||
todo!("Custom types aren't implemented yet")
|
||||
} else {
|
||||
Err(IrError::Undefined(s))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: GenIR> GenIR for Box<G> {
|
||||
fn gen_ir(
|
||||
self,
|
||||
bindings: &BindingScope,
|
||||
parent: &Identifier,
|
||||
index: u32,
|
||||
type_context: bool,
|
||||
) -> ir::Result<LinkedList<ir::expr::Expr>> {
|
||||
(*self).gen_ir(bindings, parent, index, type_context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::{ops::Range, mem::{Discriminant, self}};
|
|||
|
||||
use logos::Lexer;
|
||||
|
||||
use crate::{token::{Token, InfixRank1, InfixRank7, InfixRank6, InfixRank5, InfixRank3, InfixRank2}, cons};
|
||||
use crate::{token::{Token, InfixRank1, InfixRank6, InfixRank5, InfixRank3, InfixRank2, InfixRank4}, cons};
|
||||
use std::mem::discriminant;
|
||||
|
||||
pub mod program;
|
||||
|
@ -28,6 +28,7 @@ pub trait Parsable: Sized {
|
|||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError>;
|
||||
fn matches(l: &Token) -> bool {
|
||||
let (expected, can_zero_width) = Self::expected();
|
||||
eprintln!("{expected:?} {l:?}");
|
||||
can_zero_width || expected.contains(&discriminant(l))
|
||||
}
|
||||
}
|
||||
|
@ -218,9 +219,26 @@ impl Parsable for InfixRank3 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Parsable for InfixRank4 {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(vec![discriminant(&Token::R4Infix(InfixRank4::Range))], false)
|
||||
}
|
||||
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let span = l.span();
|
||||
match l.monch() {
|
||||
Token::R4Infix(o) => Ok(o),
|
||||
_ => Err(ParseError {
|
||||
location: span,
|
||||
expected: Self::expected().0
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for InfixRank5 {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(vec![discriminant(&Token::R5Infix(InfixRank5::Range))], false)
|
||||
(vec![discriminant(&Token::R5Infix(InfixRank5::Add))], false)
|
||||
}
|
||||
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
|
@ -237,7 +255,7 @@ impl Parsable for InfixRank5 {
|
|||
|
||||
impl Parsable for InfixRank6 {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(vec![discriminant(&Token::R6Infix(InfixRank6::Add))], false)
|
||||
(vec![discriminant(&Token::R6Infix(InfixRank6::Mul))], false)
|
||||
}
|
||||
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
|
@ -251,20 +269,3 @@ impl Parsable for InfixRank6 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for InfixRank7 {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(vec![discriminant(&Token::R7Infix(InfixRank7::Mul))], false)
|
||||
}
|
||||
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let span = l.span();
|
||||
match l.monch() {
|
||||
Token::R7Infix(o) => Ok(o),
|
||||
_ => Err(ParseError {
|
||||
location: span,
|
||||
expected: Self::expected().0
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use std::mem::{discriminant, Discriminant};
|
||||
|
||||
use crate::token::{Literal, Token};
|
||||
use crate::{token::{Literal, Token}, ir::{BindingScope, Identifier, pattern::Pattern, self, IrError}, cons, join_vec};
|
||||
|
||||
use super::{Parsable, ParseError, WrappedLexer, absorb_token_or_error};
|
||||
|
||||
|
@ -16,6 +16,22 @@ pub enum TightBindingPattern {
|
|||
Group(BindingPattern),
|
||||
}
|
||||
|
||||
impl TightBindingPattern {
|
||||
pub fn gen_ir(self, scope: &BindingScope, parent_ident: &Identifier, index: u32) -> ir::Result<(Vec<Identifier>, Pattern)> {
|
||||
match self {
|
||||
TightBindingPattern::Literal(l) => Ok((Vec::new(), Pattern::Literal(l))),
|
||||
TightBindingPattern::Symbol(s) => {
|
||||
let ident = parent_ident.subid_with_name(s, index);
|
||||
Ok((
|
||||
vec![ident.clone()],
|
||||
Pattern::Binding(ident),
|
||||
))
|
||||
}
|
||||
TightBindingPattern::Group(bp) => bp.gen_ir(scope, parent_ident, index),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for TightBindingPattern {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(
|
||||
|
@ -64,3 +80,22 @@ impl Parsable for BindingPattern {
|
|||
Ok(Self(name, fields))
|
||||
}
|
||||
}
|
||||
|
||||
impl BindingPattern {
|
||||
pub fn gen_ir(self, scope: &BindingScope, parent_ident: &Identifier, index: u32) -> ir::Result<(Vec<Identifier>, Pattern)> {
|
||||
let BindingPattern(variant, elements) = self;
|
||||
let self_ident = parent_ident.subid_generate_name(&variant, index);
|
||||
let variant_ident = scope.lookup(&variant).ok_or(IrError::Undefined(variant))?;
|
||||
let (idents, patts) = elements.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, patt)| patt.gen_ir(scope, &self_ident, idx as u32))
|
||||
.try_fold(
|
||||
(Vec::new(), Vec::with_capacity(8)),
|
||||
|(found_identifiers, found_patterns), res| {
|
||||
let (new_idents, new_patt) = res?;
|
||||
Ok((join_vec(found_identifiers, new_idents), cons(found_patterns, new_patt)))
|
||||
}
|
||||
)?;
|
||||
Ok((idents, Pattern::Variant(variant_ident.clone(), patts)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::mem::{discriminant, Discriminant};
|
||||
|
||||
use crate::{token::Token, cons};
|
||||
use crate::{token::Token, cons, ir::{self, BindingScope, Identifier}};
|
||||
|
||||
use super::{ParseError, Parsable, WrappedLexer, declaration::Declaration};
|
||||
|
||||
|
@ -32,3 +32,18 @@ fn parse_program_inner(l: &mut WrappedLexer, acc: Vec<Declaration>) -> Result<Ve
|
|||
Ok(acc)
|
||||
}
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn gen_ir(self) -> ir::Result<Vec<ir::Declaration>> {
|
||||
// We need a first pass to generate a list of all of the identifiers
|
||||
let root_scope = self.0.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, decl)| decl.get_identifier(&Identifier::ROOT, i as u32))
|
||||
.fold(BindingScope::ROOT, |scope, ident| scope.bind_single(ident));
|
||||
println!("DEBUG {root_scope:?}");
|
||||
self.0.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, decl)| decl.gen_ir(&root_scope, i as u32, Identifier::ROOT).transpose())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
26
src/token.rs
26
src/token.rs
|
@ -158,23 +158,23 @@ pub enum Token {
|
|||
/// A rank 5 infix binop (binary operator)
|
||||
///
|
||||
/// i.e. Range
|
||||
#[token("..", |_| InfixRank5::Range)]
|
||||
R5Infix(InfixRank5), //d21
|
||||
#[token("..", |_| InfixRank4::Range)]
|
||||
R4Infix(InfixRank4), //d21
|
||||
|
||||
/// A rank 6 infix binop (binary operator)
|
||||
///
|
||||
/// i.e. Addition & Subtraction
|
||||
#[token("+", |_| InfixRank6::Add)]
|
||||
#[token("-", |_| InfixRank6::Sub)]
|
||||
R6Infix(InfixRank6), //d22
|
||||
#[token("+", |_| InfixRank5::Add)]
|
||||
#[token("-", |_| InfixRank5::Sub)]
|
||||
R5Infix(InfixRank5), //d22
|
||||
|
||||
/// A rank 7 (applied first) infix binop (binary operator)
|
||||
///
|
||||
/// i.e. Multiplication, Division, and Modulo
|
||||
#[token("*", |_| InfixRank7::Mul)]
|
||||
#[token("/", |_| InfixRank7::Div)]
|
||||
#[token("%", |_| InfixRank7::Mod)]
|
||||
R7Infix(InfixRank7), //d23
|
||||
#[token("*", |_| InfixRank6::Mul)]
|
||||
#[token("/", |_| InfixRank6::Div)]
|
||||
#[token("%", |_| InfixRank6::Mod)]
|
||||
R6Infix(InfixRank6), //d23
|
||||
|
||||
/// Some literal (a constant value represented textually)
|
||||
///
|
||||
|
@ -185,7 +185,7 @@ pub enum Token {
|
|||
Literal(Literal), //d24
|
||||
|
||||
/// Some symbol, usually a variable or a type
|
||||
#[regex(r"[a-zA-Z][a-zA-Z\d]*", |lex| lex.slice().to_string(), priority = 0)]
|
||||
#[regex(r"[a-zA-Z_][a-zA-Z\d_]*", |lex| lex.slice().to_string(), priority = 0)]
|
||||
Symbol(String), //d25
|
||||
|
||||
/// An opening `[` square bracket
|
||||
|
@ -305,7 +305,7 @@ pub enum InfixRank3 {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum InfixRank5 {
|
||||
pub enum InfixRank4 {
|
||||
/// The additive operator.
|
||||
///
|
||||
/// Takes two numeric values and returns a range from the first to the second
|
||||
|
@ -313,7 +313,7 @@ pub enum InfixRank5 {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum InfixRank6 {
|
||||
pub enum InfixRank5 {
|
||||
/// The additive operator.
|
||||
///
|
||||
/// Takes two numeric values and returns their sum
|
||||
|
@ -326,7 +326,7 @@ pub enum InfixRank6 {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum InfixRank7 {
|
||||
pub enum InfixRank6 {
|
||||
/// The multiplicitive operator.
|
||||
///
|
||||
/// Takes two numeric values and returns their product
|
||||
|
|
Loading…
Reference in New Issue