Skip to content

Commit

Permalink
iexpr
Browse files Browse the repository at this point in the history
  • Loading branch information
linsyking committed Apr 4, 2023
1 parent fd3d3a2 commit 4e1826a
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 47 deletions.
24 changes: 24 additions & 0 deletions examples/exp.meow
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
true() {"T"}

false() {"F"}

zero() {"0"}

succ(x) {cat "S" x}

pred(x) {
let "S0" = "0" x
}

dr(x,y,z) {
let y = x let x = y z
}

encode(s) {
cat cat "_^"
let "$" = "\$"
let "^" = "\^"
let "\" = "\\"
s
"_$"
}
50 changes: 50 additions & 0 deletions examples/math.meow
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
zero() {"0"}

succ(x) {"S"+x}

pred(x) {
"S0" = "0";
x
}

add(x,y) {
"0" = y;
x
}

mul(x,y) {
"S" = {"0"=""; y};
x
}

digit(x) {
"1" = "S0";
"2" = "SS0";
"3" = "SSS0";
"4" = "SSSS0";
"5" = "SSSSS0";
"6" = "SSSSSS0";
"7" = "SSSSSSS0";
"8" = "SSSSSSSS0";
"9" = "SSSSSSSSS0";
x
}

exp(x,y) {
var sm = {
" 0" = "";
"S" = `"`+x+`" `;
y
};
var pre = {
"S" = "mul ";
"S0" = "";
y
};
!(pre + sm)
}

iexpr() {
var q = !(`mul digit "9" digit "3"`);
q
}
7 changes: 7 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum Expr {
MacAp(MacAp),
Var(String),
Block(Box<Block>),
IExpr(Box<Expr>),
}

#[derive(Debug, Clone)]
Expand All @@ -38,6 +39,12 @@ pub enum BStmt {
VarDefine(String, Box<Expr>),
}

#[derive(Debug, Clone)]
pub enum Tok {
Var(String),
Literal(String),
}

#[test]
fn tt() {
// let dd = Stmt{name: "ss", args: [], }
Expand Down
20 changes: 20 additions & 0 deletions src/expr.lalrpop
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::str::FromStr;
use crate::ast::{Tok};
grammar;

pub Expression: Vec<Box<Tok>> = {
Tokz*,
}

Tokz: Box<Tok> = {
Literal => Box::new(Tok::Literal(<>)),
VarName => Box::new(Tok::Var(<>)),
}

VarName: String = {
r"[a-z]?[a-z0-9_]*" => String::from_str(<>).unwrap()
}

Literal: String = {
r#""[^"]*""# => String::from_str(&<>[1..<>.len() - 1]).unwrap(),
}
6 changes: 4 additions & 2 deletions src/parse.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Term: Box<Expr> = {
MacroAp => Box::new(Expr::MacAp(<>)),
VarName => Box::new(Expr::Var(<>)),
"{" <b:BlockE> "}" => Box::new(Expr::Block(b)),
"(" <e:Expression> ")" => e
"(" <e:Expression> ")" => e,
"!(" <e:Expression> ")" => Box::new(Expr::IExpr(e)),
}

BlockE: Box<Block> = {
Expand Down Expand Up @@ -65,5 +66,6 @@ VarName: String = {
}

Literal: String = {
r#""[^"]*""# => String::from_str(&<>[1..<>.len() - 1]).unwrap()
r#""[^"]*""# => String::from_str(&<>[1..<>.len() - 1]).unwrap(),
r#"`[^`]*`"# => String::from_str(&<>[1..<>.len() - 1]).unwrap()
}
112 changes: 67 additions & 45 deletions src/prog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashMap;

use crate::ast::*;

lalrpop_mod!(pub expr); // synthesized by LALRPOP
/// Evaluate Program

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -67,6 +68,32 @@ fn apply_rule(x: &String, rules: &Vec<Rule>) -> String {
result
}

pub fn eval_macap(macap: &MacAp, context: &Box<Context>) -> String {
let mut newcontext: Context = *context.clone();
// macro application
let mac = context
.symbols
.get(&macap.name)
.expect("macro not in scope");
let mac = match mac {
Symbol::Variable(_) => panic!("variable used as macro"),
Symbol::Macro(x) => x,
};
// First evaluate arguments (by value)
let args = macap
.args
.iter()
.map(|x| eval_raw(x, context))
.collect::<Vec<String>>();
// add vars to the context
for (result, name) in args.iter().zip(mac.args.iter()) {
newcontext
.symbols
.insert(name.clone(), Symbol::Variable(result.clone()));
}
eval_block(&mac.block, &Box::new(newcontext))
}

pub fn eval_raw(expr: &Box<Expr>, context: &Box<Context>) -> String {
// Evaluate an expression in a given context.
// Will not apply rules
Expand All @@ -82,32 +109,13 @@ pub fn eval_raw(expr: &Box<Expr>, context: &Box<Context>) -> String {
Symbol::Macro(_) => panic!("macro used as variable"),
}
}
Expr::MacAp(macap) => {
let mut newcontext: Context = *context.clone();
// macro application
let mac = context
.symbols
.get(&macap.name)
.expect("macro not in scope");
let mac = match mac {
Symbol::Variable(_) => panic!("variable used as macro"),
Symbol::Macro(x) => x,
};
// First evaluate arguments (by value)
let args = macap
.args
.iter()
.map(|x| eval_raw(x, context))
.collect::<Vec<String>>();
// add vars to the context
for (result, name) in args.iter().zip(mac.args.iter()) {
newcontext
.symbols
.insert(name.clone(), Symbol::Variable(result.clone()));
}
eval_block(&mac.block, &Box::new(newcontext))
}
Expr::MacAp(macap) => eval_macap(macap, context),
Expr::Block(x) => eval_block(x, context),
Expr::IExpr(x) => {
let res = eval_raw(x, context);
let pres = &mut expr::ExpressionParser::new().parse(&res).unwrap();
take_one_para(pres, context)
}
}
}

Expand Down Expand Up @@ -150,26 +158,40 @@ pub fn eval_block(block: &Box<Block>, context: &Box<Context>) -> String {
eval(&block.expr, lcontext)
}

#[cfg(test)]
mod tests {
use std::collections::HashMap;

use crate::ast::Expr;

use super::eval;

fn eval_test(expr: &Expr) -> String {
let context = Box::new(super::Context {
symbols: HashMap::new(),
rules: vec![],
});
let newexpr = Box::new(expr.clone());
eval(&newexpr, &context)
fn take_one_para(expr: &mut Vec<Box<Tok>>, context: &Box<Context>) -> String {
// Take one argument from the expression
let first = eat_one_para(expr);
match &*first {
Tok::Literal(x) => x.clone(),
Tok::Var(x) => {
let sym = context.symbols.get(x).expect("symbol not in scope");
match sym {
Symbol::Variable(y) => y.clone(),
Symbol::Macro(y) => {
// Apply macro here
let argnum = y.args.len();
let narg = take_paras(argnum, expr, context);
let macap = MacAp {
name: x.clone(),
args: narg,
};
eval_macap(&macap, context)
}
}
}
}
}

#[test]
fn expr_eval() {
let expr1 = Expr::Literal(String::from("abc"));
assert_eq!(eval_test(&expr1), "abc".to_string());
}
fn take_paras(n: usize, expr: &mut Vec<Box<Tok>>, context: &Box<Context>) -> Vec<Box<Expr>> {
// Take n arguments from the expression
(0..n)
.map(|_| Box::new(Expr::Literal(take_one_para(expr, context))))
.collect::<Vec<Box<Expr>>>()
}

fn eat_one_para(expr: &mut Vec<Box<Tok>>) -> Box<Tok> {
// Take one argument from the expression
let sd = expr.first().expect("missing argument").clone();
expr.remove(0);
sd
}

0 comments on commit 4e1826a

Please sign in to comment.