deelang/src/emitter.rs

73 lines
1.6 KiB
Rust
Raw Normal View History

use std::io::Write;
use std::collections::HashSet;
use crate::parser;
pub struct LexicalContext<'a> {
parent: Option<&'a LexicalContext<'a>>,
local: HashSet<String>
}
impl <'a> LexicalContext<'a> {
pub fn toplevel() -> Self {
LexicalContext {
parent: None,
local: HashSet::new()
}
}
#[allow(dead_code)]
fn new(parent: &'a LexicalContext<'a>) -> Self {
LexicalContext {
parent: Some(parent),
local: HashSet::new(),
}
}
fn contains(&self, s: &str) -> bool {
self.local.contains(s) || self.parent.map_or(false, |c| c.contains(s))
}
fn insert(&mut self, s: String) -> bool {
self.local.insert(s)
}
}
pub fn emit_all(w: &mut dyn Write, ast: &Vec<parser::Stmt>, ctx: &mut LexicalContext) -> std::io::Result<()> {
for stmt in ast {
emit(w, stmt, ctx)?;
}
Ok(())
}
pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> std::io::Result<()> {
match &stmt {
parser::Stmt::ReplPrint(expr) => {
write!(w, "console.log((")?;
emit_expr(w, expr, ctx)?;
writeln!(w, "));")?;
}
parser::Stmt::Assignment(id, expr) => {
if !ctx.contains(id) {
ctx.insert(id.clone());
write!(w, "let ")?;
}
write!(w, "{} = ", id)?;
emit_expr(w, expr, ctx)?;
writeln!(w, ";")?;
}
_ => todo!(),
}
Ok(())
}
pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContext) -> std::io::Result<()> {
match &expr {
parser::Expr::Id(id) => {
write!(w, "{}", id)?;
}
parser::Expr::Atom(atom) => {
write!(w, "{}", atom)?;
}
_ => todo!(),
}
Ok(())
}