mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-24 18:39:50 -04:00
DEV: The beginnings of some shape Derivation
This commit is contained in:
parent
5ae4b91004
commit
a3a7ce57ee
@ -30,7 +30,7 @@ use abortable_parser;
|
|||||||
|
|
||||||
use crate::build::scope::Scope;
|
use crate::build::scope::Scope;
|
||||||
use crate::build::Val;
|
use crate::build::Val;
|
||||||
use crate::error::BuildError;
|
use crate::error::{BuildError, ErrorType::TypeFail};
|
||||||
|
|
||||||
pub mod printer;
|
pub mod printer;
|
||||||
pub mod walk;
|
pub mod walk;
|
||||||
@ -353,7 +353,7 @@ impl Value {
|
|||||||
Value::Int(p) => Shape::Int(p.clone()),
|
Value::Int(p) => Shape::Int(p.clone()),
|
||||||
Value::Float(p) => Shape::Float(p.clone()),
|
Value::Float(p) => Shape::Float(p.clone()),
|
||||||
Value::Str(p) => Shape::Str(p.clone()),
|
Value::Str(p) => Shape::Str(p.clone()),
|
||||||
// Symbols in a shape are placeholder. They allow a form of genericity
|
// Symbols in a shape are placeholders. They allow a form of genericity
|
||||||
// in the shape. They can be any type and are only refined down.
|
// in the shape. They can be any type and are only refined down.
|
||||||
// by their presence in an expression.
|
// by their presence in an expression.
|
||||||
Value::Symbol(p) => Shape::Symbol(p.clone()),
|
Value::Symbol(p) => Shape::Symbol(p.clone()),
|
||||||
@ -826,12 +826,43 @@ impl Expression {
|
|||||||
fn derive_shape(&self) -> Result<Shape, BuildError> {
|
fn derive_shape(&self) -> Result<Shape, BuildError> {
|
||||||
// FIXME(jwall): Implement this
|
// FIXME(jwall): Implement this
|
||||||
let shape = match self {
|
let shape = match self {
|
||||||
Expression::Simple(ref v) => v.try_into()?,
|
Expression::Simple(v) => v.try_into()?,
|
||||||
Expression::Format(def) => {
|
Expression::Format(def) => {
|
||||||
Shape::Str(PositionedItem::new("".to_owned(), def.pos.clone()))
|
Shape::Str(PositionedItem::new("".to_owned(), def.pos.clone()))
|
||||||
}
|
}
|
||||||
Expression::Not(def) => Shape::Boolean(PositionedItem::new(true, def.pos.clone())),
|
Expression::Not(def) => {
|
||||||
|
let shape = def.expr.as_ref().try_into()?;
|
||||||
|
if let Shape::Boolean(b) = shape {
|
||||||
|
Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()))
|
||||||
|
} else {
|
||||||
|
// TODO(jwall): Display implementations for shapes.
|
||||||
|
return Err(BuildError::new(
|
||||||
|
format!(
|
||||||
|
"Expected Boolean value in Not expression but got: {:?}",
|
||||||
|
shape
|
||||||
|
),
|
||||||
|
TypeFail,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
Expression::Grouped(v, _pos) => v.as_ref().try_into()?,
|
Expression::Grouped(v, _pos) => v.as_ref().try_into()?,
|
||||||
|
Expression::Range(def) => Shape::List(PositionedItem::new(
|
||||||
|
vec![Shape::Int(PositionedItem::new(0, def.start.pos().clone()))],
|
||||||
|
def.pos.clone(),
|
||||||
|
)),
|
||||||
|
Expression::Cast(def) => match def.cast_type {
|
||||||
|
CastType::Int => Shape::Int(PositionedItem::new(0, def.pos.clone())),
|
||||||
|
CastType::Str => Shape::Str(PositionedItem::new("".to_owned(), def.pos.clone())),
|
||||||
|
CastType::Float => Shape::Float(PositionedItem::new(0.0, def.pos.clone())),
|
||||||
|
CastType::Bool => Shape::Boolean(PositionedItem::new(true, def.pos.clone())),
|
||||||
|
},
|
||||||
|
Expression::Import(def) => {
|
||||||
|
// FIXME(jwall): What should this do?
|
||||||
|
Shape::Symbol(PositionedItem::new(
|
||||||
|
def.path.fragment.clone(),
|
||||||
|
def.path.pos.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
_ => Shape::Empty(Position::new(0, 0, 0)),
|
_ => Shape::Empty(Position::new(0, 0, 0)),
|
||||||
};
|
};
|
||||||
Ok(shape)
|
Ok(shape)
|
||||||
|
@ -11,10 +11,37 @@
|
|||||||
// 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::{
|
use abortable_parser::iter::SliceIter;
|
||||||
Expression, FormatArgs, FormatDef, ListDef, NotDef, Position, PositionedItem, Shape, Token,
|
use abortable_parser::Result as ParseResult;
|
||||||
TokenType, Value,
|
|
||||||
};
|
use crate::ast::{Expression, ListDef, Position, PositionedItem, Shape, Token, TokenType, Value};
|
||||||
|
use crate::iter::OffsetStrIter;
|
||||||
|
use crate::parse::expression;
|
||||||
|
use crate::tokenizer::tokenize;
|
||||||
|
|
||||||
|
macro_rules! assert_shape {
|
||||||
|
($input:expr => $shape:expr) => {{
|
||||||
|
let iter = OffsetStrIter::new($input);
|
||||||
|
let tokenized = match tokenize(iter, None) {
|
||||||
|
Ok(toks) => toks,
|
||||||
|
Err(err) => panic!(format!("failed to parse {} with error {}", $input, err)),
|
||||||
|
};
|
||||||
|
let toks = SliceIter::new(&tokenized);
|
||||||
|
if let ParseResult::Complete(_, ref expr) = expression(toks) {
|
||||||
|
assert_eq!(
|
||||||
|
match expr.derive_shape() {
|
||||||
|
Ok(shape) => shape,
|
||||||
|
Err(err) => {
|
||||||
|
panic!(format!("failed to parse {} with error {}", $input, err))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$shape
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert!(false, format!("failed to parse expression! {:?}", $input));
|
||||||
|
};
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn derive_shape_values() {
|
fn derive_shape_values() {
|
||||||
@ -89,40 +116,47 @@ fn derive_shape_values() {
|
|||||||
fn derive_shape_expressions() {
|
fn derive_shape_expressions() {
|
||||||
let expr_cases = vec![
|
let expr_cases = vec![
|
||||||
(
|
(
|
||||||
Expression::Simple(Value::Int(PositionedItem::new(3, Position::new(0, 0, 0)))),
|
"3;",
|
||||||
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
|
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Expression::Grouped(
|
"(3);",
|
||||||
Box::new(Expression::Simple(Value::Int(PositionedItem::new(
|
|
||||||
3,
|
|
||||||
Position::new(0, 0, 0),
|
|
||||||
)))),
|
|
||||||
Position::new(0, 0, 0),
|
|
||||||
),
|
|
||||||
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
|
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Expression::Format(FormatDef {
|
"\"foo {}\" % (1);",
|
||||||
template: "".to_owned(),
|
|
||||||
args: FormatArgs::List(Vec::new()),
|
|
||||||
pos: Position::new(0, 0, 0),
|
|
||||||
}),
|
|
||||||
Shape::Str(PositionedItem::new("".to_owned(), Position::new(0, 0, 0))),
|
Shape::Str(PositionedItem::new("".to_owned(), Position::new(0, 0, 0))),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Expression::Not(NotDef {
|
"not true;",
|
||||||
expr: Box::new(Expression::Simple(Value::Boolean(PositionedItem::new(
|
Shape::Boolean(PositionedItem::new(false, Position::new(1, 0, 0))),
|
||||||
true,
|
),
|
||||||
Position::new(0, 0, 0),
|
(
|
||||||
)))),
|
"0:1;",
|
||||||
pos: Position::new(1, 0, 0),
|
Shape::List(PositionedItem::new(
|
||||||
}),
|
vec![Shape::Int(PositionedItem::new(0, Position::new(0, 0, 0)))],
|
||||||
Shape::Boolean(PositionedItem::new(true, Position::new(1, 0, 0))),
|
Position::new(0, 0, 0),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"int(\"1\");",
|
||||||
|
Shape::Int(PositionedItem::new(0, Position::new(0, 0, 0))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"float(1);",
|
||||||
|
Shape::Float(PositionedItem::new(0.0, Position::new(0, 0, 0))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"str(1);",
|
||||||
|
Shape::Str(PositionedItem::new("".to_owned(), Position::new(0, 0, 0))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"bool(\"true\");",
|
||||||
|
Shape::Boolean(PositionedItem::new(true, Position::new(0, 0, 0))),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (expr, shape) in expr_cases {
|
for (expr, shape) in expr_cases {
|
||||||
assert_eq!(expr.derive_shape().unwrap(), shape);
|
assert_shape!(expr => shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user