From ca979edd7ca3f79ef844f6f0efc90a6d8dbc3773 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 15:14:18 +0100 Subject: [PATCH] Desugar variable access and assignment --- src/desugar.rs | 1 + src/desugar/expr.rs | 6 +- src/desugar/var.rs | 161 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 src/desugar/var.rs diff --git a/src/desugar.rs b/src/desugar.rs index c1037be..7402709 100644 --- a/src/desugar.rs +++ b/src/desugar.rs @@ -4,3 +4,4 @@ mod expr; mod field; mod lit; mod program; +mod var; diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 022592a..0c8e569 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -10,11 +10,11 @@ impl Expr { Self::Call(call) => call.desugar(), Self::Field(field) => field.desugar(), + Self::Var(var) => var.desugar(), - Self::Var(var) => (Self::Var(var), false), // TODO Implement Self::TableConstr(constr) => (Self::TableConstr(constr), false), // TODO Implement - Self::TableDestr(destr) => (Self::TableDestr(destr), false), // TODO Implement - Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement + Self::TableDestr(destr) => (Self::TableDestr(destr), false), // TODO Implement + Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement Self::Paren { s0, diff --git a/src/desugar/var.rs b/src/desugar/var.rs new file mode 100644 index 0000000..887d115 --- /dev/null +++ b/src/desugar/var.rs @@ -0,0 +1,161 @@ +use crate::ast::{ + Call, Expr, Field, Line, Lit, Separated, Space, StringLit, StringLitElem, TableConstr, + TableConstrElem, TableLitElem, Var, +}; +use crate::builtin::Builtin; +use crate::span::HasSpan; + +impl Var { + pub fn desugar(self) -> (Expr, bool) { + match self { + Self::Access { + s0, + index, + s1, + span, + } => { + // `[ s0 index s1 ]` + // -> `'scope()[ s0 index s1 ]` + let scope = Expr::Call(Call::NoArg { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + s0: Space::empty(span), + s1: Space::empty(span), + span, + }); + let new = Expr::Field(Field::Access { + expr: Box::new(scope), + s0: Space::empty(span), + s1: s0, + index, + s2: s1, + span, + }); + (new, true) + } + + Self::Assign { + local: None, + s0, + index, + s1, + s2, + s3, + value, + span, + } => { + // `[ s0 index s1 ] s2 = s3 value` + // -> `'scope()[ s0 index s1 ] s2 = s3 value` + let scope = Expr::Call(Call::NoArg { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + s0: Space::empty(span), + s1: Space::empty(span), + span, + }); + let new = Expr::Field(Field::Assign { + expr: Box::new(scope), + s0: Space::empty(span), + s1: s0, + index, + s2: s1, + s3: s2, + s4: s3, + value, + span, + }); + (new, true) + } + + Self::Assign { + local: Some(local), + s0, + index, + s1, + s2, + s3, + value, + span, + } => { + // `local [ s0 index s1 ] s2 = s3 value` + // --> `'setraw { 'scope(), local s0 index s1, s2 s3 value }` + let scope = Expr::Call(Call::NoArg { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + s0: Space::empty(span), + s1: Space::empty(span), + span, + }); + let elems = Separated::NonEmpty { + first_elem: TableConstrElem::Lit(TableLitElem::Positional(Box::new(scope))), + last_elems: vec![ + ( + (Space::empty(span), local.then_line(Line::Empty).then(s0)), + TableConstrElem::Lit(TableLitElem::Positional(index)), + ), + ( + (s1, s2.then_line(Line::Empty).then(s3)), + TableConstrElem::Lit(TableLitElem::Positional(value)), + ), + ], + trailing: None, + span, + }; + let constr = TableConstr { + s0: Space::empty(span), + elems, + s1: Space::empty(span), + span, + }; + let new = Expr::Call(Call::Constr { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::SetRaw, span))), + s0: Space::empty(span), + constr, + span, + }); + (new, true) + } + + Self::AccessIdent(name) => { + // `name` + // -> `[ name_str ]` + let span = name.span(); + let name_str = Expr::Lit(Lit::String(StringLit { + elems: vec![StringLitElem::Plain(name.name)], + span, + })); + let new = Expr::Var(Self::Access { + s0: Space::empty(span), + index: Box::new(name_str), + s1: Space::empty(span), + span, + }); + (new, true) + } + + Self::AssignIdent { + local, + name, + s0, + s1, + value, + span, + } => { + // `local name s0 = s1 value` + // -> `local [ name_str ] s0 = s1 value` + let name_str = Expr::Lit(Lit::String(StringLit { + elems: vec![StringLitElem::Plain(name.name)], + span: name.span, + })); + let new = Expr::Var(Self::Assign { + local, + s0: Space::empty(span), + index: Box::new(name_str), + s1: Space::empty(span), + s2: s0, + s3: s1, + value, + span, + }); + (new, true) + } + } + } +}