Blocks and statements
parent
ea33ae23bc
commit
c2c0dacb67
|
@ -1,6 +1,8 @@
|
|||
# implementation roadmap
|
||||
|
||||
- [ ] parser
|
||||
- [ ] uniform function call syntax
|
||||
- [ ] lossless syntax trees (rowan + ungrammar)
|
||||
- [ ] typechecker
|
||||
- [ ] interpreter
|
||||
- [ ] code generator
|
||||
|
@ -11,4 +13,5 @@
|
|||
- [ ] product types
|
||||
- [ ] sum types
|
||||
- [ ] variant types
|
||||
- [ ] pattern matching
|
||||
- [ ] trait / interface system
|
||||
|
|
12
example.mul
12
example.mul
|
@ -1,7 +1,9 @@
|
|||
main = () {
|
||||
print(sum_equals(1, 2, 3) == true)
|
||||
main = () -> {
|
||||
result = sum_equals(1, 2, 3);
|
||||
print(result)
|
||||
}
|
||||
|
||||
sum_equals = (x, y, sum) {
|
||||
equals(add(x, y), sum)
|
||||
}
|
||||
sum_equals = (x, y, expected) -> {
|
||||
sum = add(x, y);
|
||||
equals(sum, expected)
|
||||
}
|
||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,11 +1,22 @@
|
|||
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() {
|
||||
let mut stdin = stdin().lock();
|
||||
let mut stdout = stdout().lock();
|
||||
let parser = ExpressionParser::new();
|
||||
let expression = ExpressionParser::new();
|
||||
let statement = StatementParser::new();
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
print!("> ");
|
||||
|
@ -13,10 +24,10 @@ fn main() {
|
|||
stdin
|
||||
.read_line(&mut line)
|
||||
.expect("Failed to read from stdin");
|
||||
match parser.parse(line.as_str()) {
|
||||
Ok(parsed) => println!("{parsed:?}"),
|
||||
Err(lalrpop_util::ParseError::UnrecognizedEOF { .. }) => break,
|
||||
Err(e) => println!("Parse error: {e}"),
|
||||
if line.trim_end().ends_with(';') {
|
||||
parse!(statement, line)
|
||||
} else {
|
||||
parse!(expression, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
use crate::syntax::{Expression, Name};
|
||||
use crate::syntax::{Expression, Name, Statement};
|
||||
|
||||
grammar;
|
||||
|
||||
pub Statement: Statement = {
|
||||
<name:Name> "=" <body:Expression> ";" => Statement::Binding(name, body),
|
||||
<body:Expression> ";" => Statement::Expression(body),
|
||||
};
|
||||
|
||||
pub Expression: Expression = {
|
||||
"(" <params:Comma<Name>> ")" "{" <body:Expression> "}" => Expression::Lambda(params, Box::new(body)),
|
||||
<callee:Expression> "(" <args:Comma<Expression>> ")" => Expression::Call(Box::new(callee), args),
|
||||
"(" <params:Comma<Name>> ")" "->" <body:Expression> => Expression::Lambda(params, Box::new(body)),
|
||||
Atom => <>,
|
||||
};
|
||||
|
||||
Atom: Expression = {
|
||||
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(<>),
|
||||
Boolean => Expression::Boolean(<>),
|
||||
};
|
||||
|
||||
// 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 = {
|
||||
"true" => true,
|
||||
|
|
|
@ -1,10 +1,57 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
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)]
|
||||
pub enum Expression {
|
||||
Variable(Name),
|
||||
Block(Vec<Statement>, Box<Expression>),
|
||||
Lambda(Vec<Name>, Box<Expression>),
|
||||
Call(Box<Expression>, Vec<Expression>),
|
||||
Boolean(bool),
|
||||
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}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue