mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Simple formatting works
This commit is contained in:
parent
422569c7b4
commit
405ad2880e
@ -20,8 +20,8 @@ impl<E> From<E> for Error
|
|||||||
where
|
where
|
||||||
E: std::error::Error + Sized,
|
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
|
// FIXME(jwall): This should really have more information for debugging
|
||||||
Error {}
|
Error {}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,6 +40,18 @@ pub enum Primitive {
|
|||||||
|
|
||||||
use Primitive::{Bool, Empty, Float, Int, Str};
|
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)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Composite {
|
pub enum Composite {
|
||||||
List(Vec<Rc<Value>>),
|
List(Vec<Rc<Value>>),
|
||||||
@ -48,6 +60,35 @@ pub enum Composite {
|
|||||||
|
|
||||||
use Composite::{List, Tuple};
|
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)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
ptr: OpPointer,
|
ptr: OpPointer,
|
||||||
@ -78,6 +119,19 @@ pub enum Value {
|
|||||||
M(Module),
|
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};
|
use Value::{C, F, M, P, S, T};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -148,6 +202,8 @@ pub enum Op {
|
|||||||
// Runtime hooks
|
// Runtime hooks
|
||||||
Runtime(Hook),
|
Runtime(Hook),
|
||||||
// TODO(jwall): TRACE instruction
|
// TODO(jwall): TRACE instruction
|
||||||
|
// TODO(jwall): Format instruction
|
||||||
|
Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
use super::ir::Val;
|
use super::ir::Val;
|
||||||
|
@ -16,7 +16,7 @@ use std::rc::Rc;
|
|||||||
use super::scope::Stack;
|
use super::scope::Stack;
|
||||||
use super::Composite::{List, Tuple};
|
use super::Composite::{List, Tuple};
|
||||||
use super::Op::{
|
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,
|
InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return,
|
||||||
SelectJump, Sub, Sym, Typ, Val,
|
SelectJump, Sub, Sym, Typ, Val,
|
||||||
};
|
};
|
||||||
@ -632,3 +632,18 @@ fn simple_not_expr() {
|
|||||||
"not 1!=1;" => P(Bool(true)),
|
"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())),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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::Primitive;
|
||||||
use crate::build::opcode::Value::{C, F, M, P, T};
|
use crate::build::opcode::Value::{C, F, M, P, T};
|
||||||
use crate::build::opcode::{Hook, Op};
|
use crate::build::opcode::{Hook, Op};
|
||||||
@ -168,7 +168,24 @@ impl AST {
|
|||||||
Self::translate_expr(*expr, &mut ops);
|
Self::translate_expr(*expr, &mut ops);
|
||||||
}
|
}
|
||||||
Expression::Fail(_) => unimplemented!("Fail expressions are not implmented yet"),
|
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::Func(_) => unimplemented!("Func expressions are not implmented yet"),
|
||||||
Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"),
|
Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"),
|
||||||
Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"),
|
Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"),
|
||||||
|
@ -18,13 +18,14 @@ use std::rc::Rc;
|
|||||||
use super::pointer::OpPointer;
|
use super::pointer::OpPointer;
|
||||||
use super::runtime;
|
use super::runtime;
|
||||||
use super::scope::Stack;
|
use super::scope::Stack;
|
||||||
use super::{Error, Op, Primitive, Value};
|
|
||||||
|
|
||||||
use super::Composite::{List, Tuple};
|
use super::Composite::{List, Tuple};
|
||||||
use super::Hook;
|
use super::Hook;
|
||||||
use super::Primitive::{Bool, Empty, Float, Int, Str};
|
use super::Primitive::{Bool, Empty, Float, Int, Str};
|
||||||
use super::Value::{C, F, M, P, S, T};
|
use super::Value::{C, F, M, P, S, T};
|
||||||
|
use super::{Error, Op, Primitive, Value};
|
||||||
use super::{Func, Module};
|
use super::{Func, Module};
|
||||||
|
use crate::ast::Position;
|
||||||
|
use crate::build::format::{ExpressionFormatter, FormatRenderer, SimpleFormatter};
|
||||||
|
|
||||||
pub struct VM {
|
pub struct VM {
|
||||||
stack: Vec<Rc<Value>>,
|
stack: Vec<Rc<Value>>,
|
||||||
@ -123,6 +124,7 @@ impl<'a> VM {
|
|||||||
}
|
}
|
||||||
Op::Typ => self.op_typ()?,
|
Op::Typ => self.op_typ()?,
|
||||||
Op::Runtime(h) => self.op_runtime(h)?,
|
Op::Runtime(h) => self.op_runtime(h)?,
|
||||||
|
Op::Format => self.op_format()?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -719,4 +721,28 @@ impl<'a> VM {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.handle(&self.path, h, &mut self.stack)
|
.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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user