Blocks and statements

main
mat ess 2023-04-30 23:05:39 -04:00
parent ea33ae23bc
commit c2c0dacb67
5 changed files with 91 additions and 16 deletions

View File

@ -1,6 +1,8 @@
# implementation roadmap # implementation roadmap
- [ ] parser - [ ] parser
- [ ] uniform function call syntax
- [ ] lossless syntax trees (rowan + ungrammar)
- [ ] typechecker - [ ] typechecker
- [ ] interpreter - [ ] interpreter
- [ ] code generator - [ ] code generator
@ -11,4 +13,5 @@
- [ ] product types - [ ] product types
- [ ] sum types - [ ] sum types
- [ ] variant types - [ ] variant types
- [ ] pattern matching
- [ ] trait / interface system - [ ] trait / interface system

View File

@ -1,7 +1,9 @@
main = () { main = () -> {
print(sum_equals(1, 2, 3) == true) result = sum_equals(1, 2, 3);
print(result)
} }
sum_equals = (x, y, sum) { sum_equals = (x, y, expected) -> {
equals(add(x, y), sum) sum = add(x, y);
equals(sum, expected)
} }

View File

@ -1,11 +1,22 @@
use std::io::{stdin, stdout, BufRead, Write}; use std::io::{stdin, stdout, BufRead, Write};
use mul::parser::ExpressionParser; use mul::parser::{ExpressionParser, StatementParser};
macro_rules! parse {
($parser:expr, $line:expr) => {
match $parser.parse($line.as_str()) {
Ok(parsed) => println!("{parsed:?}"),
Err(lalrpop_util::ParseError::UnrecognizedEOF { .. }) => break,
Err(e) => println!("Parse error: {e}"),
}
};
}
fn main() { fn main() {
let mut stdin = stdin().lock(); let mut stdin = stdin().lock();
let mut stdout = stdout().lock(); let mut stdout = stdout().lock();
let parser = ExpressionParser::new(); let expression = ExpressionParser::new();
let statement = StatementParser::new();
loop { loop {
let mut line = String::new(); let mut line = String::new();
print!("> "); print!("> ");
@ -13,10 +24,10 @@ fn main() {
stdin stdin
.read_line(&mut line) .read_line(&mut line)
.expect("Failed to read from stdin"); .expect("Failed to read from stdin");
match parser.parse(line.as_str()) { if line.trim_end().ends_with(';') {
Ok(parsed) => println!("{parsed:?}"), parse!(statement, line)
Err(lalrpop_util::ParseError::UnrecognizedEOF { .. }) => break, } else {
Err(e) => println!("Parse error: {e}"), parse!(expression, line)
} }
} }
} }

View File

@ -1,19 +1,31 @@
use crate::syntax::{Expression, Name}; use crate::syntax::{Expression, Name, Statement};
grammar; grammar;
pub Statement: Statement = {
<name:Name> "=" <body:Expression> ";" => Statement::Binding(name, body),
<body:Expression> ";" => Statement::Expression(body),
};
pub Expression: Expression = { pub Expression: Expression = {
"(" <params:Comma<Name>> ")" "{" <body:Expression> "}" => Expression::Lambda(params, Box::new(body)), "(" <params:Comma<Name>> ")" "->" <body:Expression> => Expression::Lambda(params, Box::new(body)),
<callee:Expression> "(" <args:Comma<Expression>> ")" => Expression::Call(Box::new(callee), args), Atom => <>,
};
Atom: Expression = {
Name => Expression::Variable(<>), Name => Expression::Variable(<>),
"{" <statements:Statement*> <result:Expression> "}" => Expression::Block(statements, Box::new(result)),
<callee:Atom> "(" <args:Comma<Expression>> ")" => Expression::Call(Box::new(callee), args),
Integer => Expression::Integer(<>), Integer => Expression::Integer(<>),
Boolean => Expression::Boolean(<>), Boolean => Expression::Boolean(<>),
}; };
// TODO: decide on identifier syntax // TODO: decide on identifier syntax
Name: Name = r"[a-zA-Z_]+" => <>.to_string(); Name: Name =
r"[a-zA-Z_]+" => <>.to_string();
Integer: i64 = r"[0-9]+" => <>.parse::<i64>().unwrap(); Integer: i64 =
r"[0-9]+" => <>.parse::<i64>().unwrap();
Boolean: bool = { Boolean: bool = {
"true" => true, "true" => true,

View File

@ -1,10 +1,57 @@
use std::fmt::Display;
pub type Name = String; pub type Name = String;
#[derive(Debug)]
pub enum Statement {
Binding(Name, Expression),
Expression(Expression),
}
impl Display for Statement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Statement::Binding(name, body) => write!(f, "{name} = {body};"),
Statement::Expression(body) => write!(f, "{body};"),
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum Expression { pub enum Expression {
Variable(Name), Variable(Name),
Block(Vec<Statement>, Box<Expression>),
Lambda(Vec<Name>, Box<Expression>), Lambda(Vec<Name>, Box<Expression>),
Call(Box<Expression>, Vec<Expression>), Call(Box<Expression>, Vec<Expression>),
Boolean(bool), Boolean(bool),
Integer(i64), Integer(i64),
} }
impl Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expression::Variable(name) => write!(f, "{name}"),
Expression::Block(statements, result) => {
writeln!(f, "{{")?;
for statement in statements {
writeln!(f, "\t{statement}")?;
}
writeln!(f, "\t{result}")?;
writeln!(f, "}}")
}
Expression::Lambda(params, body) => write!(f, "({}) -> {body}", params.join(", ")),
Expression::Call(callee, args) => {
write!(f, "{callee}(")?;
if let Some(arg) = args.first() {
write!(f, "{arg}")?;
}
for arg in args.iter().skip(1) {
write!(f, ", {arg}")?;
}
write!(f, ")")
}
Expression::Boolean(v) => write!(f, "{v}"),
Expression::Integer(v) => write!(f, "{v}"),
}
}
}