DEV: Simple formatting works

This commit is contained in:
Jeremy Wall 2019-08-03 16:53:43 -05:00
parent 422569c7b4
commit 405ad2880e
5 changed files with 121 additions and 7 deletions

View File

@ -20,7 +20,7 @@ impl<E> From<E> for Error
where
E: std::error::Error + Sized,
{
fn from(_e: E) -> Error {
fn from(_e: E) -> Self {
// FIXME(jwall): This should really have more information for debugging
Error {}
}

View File

@ -40,6 +40,18 @@ pub enum Primitive {
use Primitive::{Bool, Empty, Float, Int, Str};
impl From<&Primitive> for String {
fn from(p: &Primitive) -> Self {
match p {
Int(i) => format!("{}", i),
Float(f) => format!("{}", f),
Str(s) => format!("{}", s),
Bool(b) => format!("{}", b),
Empty => "NULL".to_owned(),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Composite {
List(Vec<Rc<Value>>),
@ -48,6 +60,35 @@ pub enum Composite {
use Composite::{List, Tuple};
impl From<&Composite> for String {
fn from(c: &Composite) -> Self {
let mut buf = String::new();
match c {
&List(ref elems) => {
buf.push_str("[");
for e in elems.iter() {
let val: String = e.as_ref().into();
buf.push_str(&val);
buf.push_str(",");
}
buf.push_str("]");
}
&Tuple(ref flds) => {
buf.push_str("{");
for &(ref k, ref v) in flds.iter() {
buf.push_str(&k);
buf.push_str(" = ");
let val: String = v.as_ref().into();
buf.push_str(&val);
buf.push_str(",");
}
buf.push_str("}");
}
}
buf
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Func {
ptr: OpPointer,
@ -78,6 +119,19 @@ pub enum Value {
M(Module),
}
impl From<&Value> for String {
fn from(v: &Value) -> Self {
match v {
&S(ref s) => s.clone(),
&P(ref p) => p.into(),
&C(ref c) => c.into(),
&T(_) => "<Thunk>".to_owned(),
&F(_) => "<Func>".to_owned(),
&M(_) => "<Module>".to_owned(),
}
}
}
use Value::{C, F, M, P, S, T};
#[derive(Debug, PartialEq, Clone)]
@ -148,6 +202,8 @@ pub enum Op {
// Runtime hooks
Runtime(Hook),
// TODO(jwall): TRACE instruction
// TODO(jwall): Format instruction
Format,
}
use super::ir::Val;

View File

@ -16,7 +16,7 @@ use std::rc::Rc;
use super::scope::Stack;
use super::Composite::{List, Tuple};
use super::Op::{
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, Index, InitList,
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Format, Func, Index, InitList,
InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return,
SelectJump, Sub, Sym, Typ, Val,
};
@ -632,3 +632,18 @@ fn simple_not_expr() {
"not 1!=1;" => P(Bool(true)),
)
}
#[test]
fn simple_format_expr() {
assert_cases![
vec![
InitList,
Val(Int(1)),
Element,
Val(Int(2)),
Element,
Val(Str("@@".to_owned())),
Format,
] => P(Str("12".to_owned())),
];
}

View File

@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::ast::{BinaryExprType, Expression, Statement, Value};
use crate::ast::{BinaryExprType, Expression, Statement, Value, FormatArgs};
use crate::build::opcode::Primitive;
use crate::build::opcode::Value::{C, F, M, P, T};
use crate::build::opcode::{Hook, Op};
@ -168,7 +168,24 @@ impl AST {
Self::translate_expr(*expr, &mut ops);
}
Expression::Fail(_) => unimplemented!("Fail expressions are not implmented yet"),
Expression::Format(_) => unimplemented!("Format expressions are not implmented yet"),
Expression::Format(def) => {
match def.args {
FormatArgs::List(elems) => {
ops.push(Op::InitList);
for e in elems {
Self::translate_expr(e, &mut ops);
ops.push(Op::Element);
}
}
FormatArgs::Single(e) => {
ops.push(Op::InitList);
Self::translate_expr(*e, &mut ops);
ops.push(Op::Element);
}
}
ops.push(Op::Val(Primitive::Str(def.template)));
ops.push(Op::Format);
}
Expression::Func(_) => unimplemented!("Func expressions are not implmented yet"),
Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"),
Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"),

View File

@ -18,13 +18,14 @@ use std::rc::Rc;
use super::pointer::OpPointer;
use super::runtime;
use super::scope::Stack;
use super::{Error, Op, Primitive, Value};
use super::Composite::{List, Tuple};
use super::Hook;
use super::Primitive::{Bool, Empty, Float, Int, Str};
use super::Value::{C, F, M, P, S, T};
use super::{Error, Op, Primitive, Value};
use super::{Func, Module};
use crate::ast::Position;
use crate::build::format::{ExpressionFormatter, FormatRenderer, SimpleFormatter};
pub struct VM {
stack: Vec<Rc<Value>>,
@ -123,6 +124,7 @@ impl<'a> VM {
}
Op::Typ => self.op_typ()?,
Op::Runtime(h) => self.op_runtime(h)?,
Op::Format => self.op_format()?,
};
}
Ok(())
@ -719,4 +721,28 @@ impl<'a> VM {
.borrow_mut()
.handle(&self.path, h, &mut self.stack)
}
fn op_format(&mut self) -> Result<(), Error> {
let template = self.pop()?;
let template = match template.as_ref() {
&P(Str(ref s)) => s.clone(),
_ => return Err(dbg!(Error {})),
};
let args = self.pop()?;
let args: Vec<&Value> = match args.as_ref() {
&C(List(ref elems)) => elems.iter().map(|v| v.as_ref()).collect(),
_ => return Err(dbg!(Error {})),
};
let f = if args.len() == 1 {
unimplemented!("Expression formatters are not implemented yet");
} else {
SimpleFormatter::new(template, args)
};
// TODO(jwall): Position should be valid here.
match dbg!(f.render(&Position::new(0, 0, 0))) {
Err(_e) => return Err(dbg!(Error {})),
Ok(s) => self.push(Rc::new(P(Str(s))))?,
}
Ok(())
}
}