73 lines
1.6 KiB
Rust
73 lines
1.6 KiB
Rust
|
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(())
|
||
|
}
|