IR generation is (almost) done!!!

This commit is contained in:
Emi Simpson 2022-04-23 21:52:30 -04:00
parent 250d40dab7
commit 9ddbf38ecb
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
14 changed files with 771 additions and 59 deletions

View File

@ -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

92
src/ir/expr.rs Normal file
View File

@ -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())
}

118
src/ir/mod.rs Normal file
View File

@ -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)))
}
}

10
src/ir/pattern.rs Normal file
View File

@ -0,0 +1,10 @@
use crate::token::Literal;
use super::Identifier;
#[derive(Debug)]
pub enum Pattern {
Literal(Literal),
Binding(Identifier),
Variant(Identifier, Vec<Pattern>),
}

73
src/ir/types.rs Normal file
View File

@ -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",
}
)
}
}

32
src/ir/value.rs Normal file
View File

@ -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!(),
}
}
}

View File

@ -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
}

View File

@ -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))
}
}

View File

@ -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),

View File

@ -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)
}
}

View File

@ -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
}),
}
}
}

View File

@ -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)))
}
}

View File

@ -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()
}
}

View File

@ -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