Skip to content

Commit

Permalink
Merge pull request #196 from JSAbrahams/v0.2.2
Browse files Browse the repository at this point in the history
V0.2.2
  • Loading branch information
JSAbrahams authored Jan 5, 2020
2 parents 0741180 + 1d87edc commit 3065bcd
Show file tree
Hide file tree
Showing 77 changed files with 1,084 additions and 692 deletions.
18 changes: 17 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mamba"
version = "0.2.1"
version = "0.2.2"
authors = ["Joel Abrahams <[email protected]>"]
description = "A transpiler which translates Mamba to Python 3 files"
edition = "2018"
Expand All @@ -23,3 +23,4 @@ clap = {version = "2.33", features = ["yaml"]}
leg = "0.1.3"
pathdiff = "0.1.0"
glob = "0.3.0"
itertools = "0.8.2"
3 changes: 3 additions & 0 deletions src/core/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub enum Core {
num: String,
exp: String
},
DocStr {
_str: String
},
Str {
_str: String
},
Expand Down
1 change: 1 addition & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn to_py(core: &Core, ind: usize) -> String {
format!("{}[{}]", lit, comma_delimited(generics, ind))
},
Core::IdType { lit, ty } => format!("{}: {}", lit, to_py(ty, ind)),
Core::DocStr { _str } => format!("\"\"\"{}\"\"\"", _str),
Core::Str { _str } => format!("\"{}\"", _str),
Core::FStr { _str } => format!("f\"{}\"", _str),
Core::Int { int } => int.clone(),
Expand Down
4 changes: 4 additions & 0 deletions src/desugar/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub fn desugar_call(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
function: Box::from(desugar_node(name, imp, state)?),
args: desugar_vec(args, imp, state)?
},
Node::ConstructorCall { name, args } => Core::FunctionCall {
function: Box::from(desugar_node(name, imp, &state.is_constructor(true))?),
args: desugar_vec(args, imp, state)?
},
other => panic!("Expected call flow but was: {:?}.", other)
})
}
2 changes: 1 addition & 1 deletion src/desugar/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub fn desugar_class(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResu
_ => false
});
stmts.append(&mut non_variables);
final_definitions = stmts.clone();
final_definitions = stmts;

Core::ClassDef {
name: Box::from(desugar_node(id, imp, state)?),
Expand Down
2 changes: 1 addition & 1 deletion src/desugar/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn desugar_definition(ast: &AST, imp: &mut Imports, state: &State) -> Desuga
Core::VarDef {
private: *private,
id: Box::from(id.clone()),
right: match (id.clone(), expression) {
right: match (id, expression) {
(_, Some(expr)) => Box::from(desugar_node(&expr, imp, &state)?),
(Core::Tuple { elements }, None) =>
Box::from(Core::Tuple { elements: vec![Core::None; elements.len()] }),
Expand Down
19 changes: 10 additions & 9 deletions src/desugar/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::desugar::state::State;
use crate::desugar::ty::desugar_type;
use crate::parser::ast::Node;
use crate::parser::ast::AST;
use crate::type_checker::context::ty::concrete::concrete_to_python;

// TODO return imports instead of modifying mutable reference
pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResult {
Expand Down Expand Up @@ -48,6 +49,7 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
num: num.clone(),
exp: if exp.is_empty() { String::from("0") } else { exp.clone() }
},
Node::DocStr { lit } => Core::DocStr { _str: lit.clone() },
Node::Str { lit, expressions } =>
if expressions.is_empty() {
Core::Str { _str: lit.clone() }
Expand All @@ -70,7 +72,9 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul

Node::Undefined => Core::None,
Node::IdType { .. } => desugar_type(ast, imp, state)?,
Node::Id { lit } => Core::Id { lit: lit.clone() },
Node::Id { lit } => Core::Id {
lit: if state.is_constructor { concrete_to_python(lit) } else { lit.clone() }
},
Node::_Self => Core::Id { lit: String::from("self") },
Node::Init => Core::Id { lit: String::from("init") },
Node::Bool { lit } => Core::Bool { _bool: *lit },
Expand Down Expand Up @@ -215,7 +219,8 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
}
},

Node::FunctionCall { .. } | Node::PropertyCall { .. } => desugar_call(ast, imp, state)?,
Node::FunctionCall { .. } | Node::PropertyCall { .. } | Node::ConstructorCall { .. } =>
desugar_call(ast, imp, state)?,

Node::AnonFun { args, body } => Core::AnonFun {
args: desugar_vec(args, imp, &state.expand_ty(false))?,
Expand Down Expand Up @@ -249,12 +254,9 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
},
Node::Script { statements } =>
Core::Block { statements: desugar_vec(statements, imp, state)? },
Node::File { modules, imports, .. } => {
let mut imports = desugar_vec(imports, imp, state)?;
Node::File { modules, .. } => {
let mut modules = desugar_vec(modules, imp, state)?;
imports.append(&mut imp.imports.clone().into_iter().collect());

let mut statements = imports;
let mut statements = imp.imports.clone();
statements.append(&mut modules);
Core::Block { statements }
}
Expand Down Expand Up @@ -290,7 +292,6 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
Node::Step { .. } => panic!("Step cannot be top level."),
Node::Raises { expr_or_stmt, .. } => desugar_node(expr_or_stmt, imp, state)?,
Node::Raise { error } => Core::Raise { error: Box::from(desugar_node(error, imp, state)?) },
Node::Retry { .. } => return Err(UnimplementedErr::new(ast, "retry")),

Node::Handle { expr_or_stmt, cases } => {
let assign_to = if let Node::VariableDef { id_maybe_type, .. } = &expr_or_stmt.node {
Expand Down Expand Up @@ -351,7 +352,7 @@ pub fn desugar_node(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
let core = if let Some(assign_to) = assign_to {
match core {
Core::Block { .. } | Core::Return { .. } => core,
expr => Core::Assign { left: Box::from(assign_to), right: Box::from(expr.clone()) }
expr => Core::Assign { left: Box::from(assign_to), right: Box::from(expr) }
}
} else {
core
Expand Down
11 changes: 9 additions & 2 deletions src/desugar/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@ use crate::core::construct::Core;
// TODO remove expect_expr once type checker augments AST
#[derive(Clone, Debug)]
pub struct State {
pub tup: usize,
pub tup: usize,
pub interface: bool,
pub expand_ty: bool,
pub is_constructor: bool,
pub assign_to: Option<Core>
}

impl State {
pub fn new() -> State { State { tup: 1, interface: false, expand_ty: true, assign_to: None } }
pub fn new() -> State {
State { tup: 1, interface: false, expand_ty: true, assign_to: None, is_constructor: false }
}

pub fn in_tup(&self, tup: usize) -> State { State { tup, ..self.clone() } }

pub fn in_interface(&self, interface: bool) -> State { State { interface, ..self.clone() } }

pub fn expand_ty(&self, expand_ty: bool) -> State { State { expand_ty, ..self.clone() } }

pub fn is_constructor(&self, is_constructor: bool) -> State {
State { is_constructor, ..self.clone() }
}

pub fn assign_to(&self, assign_to: Option<&Core>) -> State {
State { assign_to: assign_to.cloned(), ..self.clone() }
}
Expand Down
16 changes: 14 additions & 2 deletions src/desugar/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,22 @@ pub fn desugar_type(ast: &AST, imp: &mut Imports, state: &State) -> DesugarResul
ty: Box::from(desugar_node(ty, imp, state)?)
}
} else {
Core::Id { lit: lit.clone() }
Core::Id {
lit: if state.is_constructor {
concrete_to_python(lit)
} else {
lit.clone()
}
}
}
} else {
Core::Id { lit: lit.clone() }
Core::Id {
lit: if state.is_constructor {
concrete_to_python(lit)
} else {
lit.clone()
}
}
},
Node::_Self => Core::Id { lit: String::from("self") },
_ => desugar_node(id, imp, state)?
Expand Down
7 changes: 5 additions & 2 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::path::PathBuf;

use crate::lexer::common::State;
use crate::lexer::lex_result::{LexResult, LexResults};
use crate::lexer::pass::pass;
use crate::lexer::state::State;
use crate::lexer::tokenize::into_tokens;

pub mod lex_result;
pub mod token;

#[macro_use]
mod common;
mod state;
mod pass;
mod tokenize;

pub type TokenizeInput = (String, Option<PathBuf>);
Expand Down Expand Up @@ -57,6 +59,7 @@ pub fn tokenize(input: &str) -> LexResult {
}
tokens.append(&mut state.flush_indents());

let tokens = pass(&tokens);
Ok(tokens)
}

Expand Down
73 changes: 73 additions & 0 deletions src/lexer/pass/docstring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::lexer::pass::Pass;
use crate::lexer::token::{Lex, Token};

pub struct DocString {
front: Option<Lex>,
middle: Option<Lex>,
back: Option<Lex>
}

impl DocString {
pub fn new() -> DocString { DocString { front: None, middle: None, back: None } }

fn add(&mut self, lex: &Lex) {
self.front = self.middle.clone();
self.middle = self.back.clone();
self.back = Some(lex.clone());
}

fn get(&mut self) -> Vec<Lex> {
match (self.front.clone(), self.middle.clone(), self.back.clone()) {
(Some(front), Some(middle), Some(back)) =>
match (front.token, middle.token, back.token) {
(Token::Str(f_str, _), Token::Str(doc_str, _), Token::Str(b_str, _)) =>
if f_str.is_empty() && b_str.is_empty()
// No spaces in between
&& front.pos.end.pos == middle.pos.start.pos
&& middle.pos.end.pos == back.pos.start.pos
{
self.front = None;
self.middle = None;
self.back = None;
return vec![Lex::new(&front.pos.start, Token::DocStr(doc_str))];
},
_ => {}
},
_ => {}
};

if let Some(lex) = &self.front.clone() {
self.front = None;
vec![lex.clone()]
} else {
vec![]
}
}

fn flush(&mut self) -> Vec<Lex> {
let mut remaining = vec![];
if let Some(lex) = &self.front {
remaining.push(lex.clone());
}
if let Some(lex) = &self.middle {
remaining.push(lex.clone());
}
if let Some(lex) = &self.back {
remaining.push(lex.clone());
}
remaining
}
}

impl Pass for DocString {
fn modify(&mut self, input: &[Lex]) -> Vec<Lex> {
let mut out = vec![];
for lex in input {
self.add(lex);
out.append(&mut self.get())
}

out.append(&mut self.flush());
out
}
}
18 changes: 18 additions & 0 deletions src/lexer/pass/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use crate::lexer::pass::docstring::DocString;
use crate::lexer::token::Lex;

mod docstring;

pub fn pass(input: &[Lex]) -> Vec<Lex> {
let passes: Vec<Box<dyn Pass>> = vec![Box::from(DocString::new())];

let mut input = input.to_vec();
for mut pass in passes {
input = pass.modify(&input);
}
input
}

trait Pass {
fn modify(&mut self, input: &[Lex]) -> Vec<Lex>;
}
9 changes: 8 additions & 1 deletion src/lexer/common.rs → src/lexer/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,15 @@ impl State {
res.append(&mut self.newlines);
res.push(Lex::new(&self.pos, token.clone()));

// TODO streamline application logic for multiline strings
self.cur_indent = self.line_indent;
self.pos = self.pos.clone().offset_pos(token.width());
self.pos = self.pos.clone().offset_pos(token.clone().width());
if let Token::Str(_str, _) = &token {
self.pos = self.pos.clone().offset_line(_str.lines().count().clone() as i32);
} else if let Token::DocStr(_str) = &token {
self.pos = self.pos.clone().offset_line(_str.lines().count().clone() as i32);
}

res
}

Expand Down
Loading

0 comments on commit 3065bcd

Please sign in to comment.