Skip to content

Commit

Permalink
fix:
Browse files Browse the repository at this point in the history
- Use symbol instead of two different items
  • Loading branch information
linsyking committed Apr 3, 2023
1 parent 70f3aa4 commit fd3d3a2
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 19 deletions.
16 changes: 15 additions & 1 deletion examples/syn.meow
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,23 @@ if(c,x,y) {
"F$" = encode(y);
cc
};
decode(enc)
decode(enc)
}

in(x,y) {
eq(y,{x=""; y})
}

encode_add(s,x) {
x = "\" + x;
s
}

decode_add(s,x) {
"\" + x = x;
s
}

ife(x) {
eq(x,"")
}
18 changes: 16 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustyline::error::ReadlineError;
use std::env::args;

mod ast;
Expand All @@ -18,13 +19,26 @@ fn main() {
.expect("unexpected token!");
let context = &mut Box::new(prog::Context::new());
prog::eval_prog(res, context);

// Rustyline
let mut rl = rustyline::DefaultEditor::new().unwrap();
loop {
let mut line = String::new();
let line: String;
let readline = rl.readline("> ");
match readline {
Ok(l) => line = l.trim().to_string(),
Err(_) => println!("invalid input"),
Err(ReadlineError::Interrupted) => {
println!("Interrupted");
break;
}
Err(ReadlineError::Eof) => {
println!("EOF");
break;
}
Err(_) => {
println!("invalid input");
break;
}
}
let expr = parse::ExpressionParser::new()
.parse(line.as_str())
Expand Down
50 changes: 34 additions & 16 deletions src/prog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ struct Rule {
y: String,
}

#[derive(Debug, Clone)]
pub enum Symbol {
Variable(String),
Macro(Stmt),
}

#[derive(Debug, Clone)]
pub struct Context {
variables: HashMap<String, String>,
macros: HashMap<String, Stmt>,
symbols: HashMap<String, Symbol>,
rules: Vec<Rule>,
}

impl Context {
pub fn new() -> Self {
Context {
variables: HashMap::new(),
macros: HashMap::new(),
symbols: HashMap::new(),
rules: vec![],
}
}
Expand All @@ -45,13 +49,19 @@ pub fn eval_prog(prog: Box<Prog>, context: &mut Box<Context>) {
pub fn eval_stmt(stmt: Stmt, context: &mut Box<Context>) {
// Add a macro to the context
// Context will be modified
context.as_mut().macros.insert(stmt.name.clone(), stmt);
context
.as_mut()
.symbols
.insert(stmt.name.clone(), Symbol::Macro(stmt));
}

fn apply_rule(x: &String, rules: &Vec<Rule>) -> String {
// apply rules to a string
let mut result = x.clone();
for rule in rules.iter().rev() {
if rule.y.is_empty() {
panic!("empty rule detected");
}
result = result.replace(rule.y.as_str(), rule.x.as_str());
}
result
Expand All @@ -66,16 +76,23 @@ pub fn eval_raw(expr: &Box<Expr>, context: &Box<Context>) -> String {
Expr::Var(x) =>
// use variables
{
context
.variables
.get(x)
.expect("variable not in scope")
.clone()
let sym = context.symbols.get(x).expect("variable not in scope");
match sym {
Symbol::Variable(x) => x.clone(),
Symbol::Macro(_) => panic!("macro used as variable"),
}
}
Expr::MacAp(macap) => {
let mut newcontext: Context = *context.clone();
// macro application
let mac = context.macros.get(&macap.name).expect("macro not in scope");
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
Expand All @@ -84,7 +101,9 @@ pub fn eval_raw(expr: &Box<Expr>, context: &Box<Context>) -> String {
.collect::<Vec<String>>();
// add vars to the context
for (result, name) in args.iter().zip(mac.args.iter()) {
newcontext.variables.insert(name.clone(), result.clone());
newcontext
.symbols
.insert(name.clone(), Symbol::Variable(result.clone()));
}
eval_block(&mac.block, &Box::new(newcontext))
}
Expand Down Expand Up @@ -117,8 +136,8 @@ pub fn eval_block(block: &Box<Block>, context: &Box<Context>) -> String {
match &**bs {
BStmt::VarDefine(name, expr) => {
lcontext
.variables
.insert(name.clone(), eval_raw(expr, lcontext));
.symbols
.insert(name.clone(), Symbol::Variable(eval_raw(expr, lcontext)));
}
BStmt::MEq(lv, rv) => {
lcontext.rules.push(Rule {
Expand All @@ -141,8 +160,7 @@ mod tests {

fn eval_test(expr: &Expr) -> String {
let context = Box::new(super::Context {
variables: HashMap::new(),
macros: HashMap::new(),
symbols: HashMap::new(),
rules: vec![],
});
let newexpr = Box::new(expr.clone());
Expand Down

0 comments on commit fd3d3a2

Please sign in to comment.