mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-25 18:49:50 -04:00
DEV: Plugin the VM to our FileBuilder.
Most of the tests do not yet pass and the main.rs doesn't compile but we are snapshotting here so we can start fixing unit tests before we hook directly into the main.rs.
This commit is contained in:
parent
156b55271e
commit
e256abfee6
@ -23,37 +23,39 @@ use crate::convert::ConverterRegistry;
|
|||||||
|
|
||||||
fn assert_build(input: &str) {
|
fn assert_build(input: &str) {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = MemoryCache::new();
|
let out_buffer: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err_buffer: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new("<Eval>", &i_paths, Rc::new(RefCell::new(cache)), ®istry);
|
let mut b = FileBuilder::new("<Eval>", &i_paths, out_buffer, err_buffer);
|
||||||
b.enable_validate_mode();
|
b.enable_validate_mode();
|
||||||
b.eval_string(input).unwrap();
|
b.eval_string(input).unwrap();
|
||||||
if !b.assert_collector.success {
|
// FIXME(jwall): What do we want to do with the assert collector?
|
||||||
assert!(false, b.assert_collector.failures);
|
//if !b.assert_collector.success {
|
||||||
}
|
// assert!(false, b.assert_collector.failures);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = MemoryCache::new();
|
let out_buffer: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err_buffer: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new("<Eval>", &i_paths, Rc::new(RefCell::new(cache)), ®istry);
|
let mut b = FileBuilder::new("<Eval>", &i_paths, out_buffer, err_buffer);
|
||||||
b.enable_validate_mode();
|
b.enable_validate_mode();
|
||||||
let err = b.eval_string(input);
|
let err = b.eval_string(input);
|
||||||
match err {
|
match err {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
for r in expect.iter() {
|
for r in expect.iter() {
|
||||||
if !b.assert_collector.success {
|
// FIXME(jwall): Assert collector...
|
||||||
if let None = r.find(&b.assert_collector.failures) {
|
//if !b.assert_collector.success {
|
||||||
assert!(
|
// if let None = r.find(&b.assert_collector.failures) {
|
||||||
false,
|
// assert!(
|
||||||
"[{}] was not found in Assertion Failures:\n{}",
|
// false,
|
||||||
r, b.assert_collector.failures
|
// "[{}] was not found in Assertion Failures:\n{}",
|
||||||
);
|
// r, b.assert_collector.failures
|
||||||
}
|
// );
|
||||||
} else {
|
// }
|
||||||
assert!(false, "Building input Did not panic!");
|
//} else {
|
||||||
}
|
// assert!(false, "Building input Did not panic!");
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(ref err) => {
|
Err(ref err) => {
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//! The format string logic for ucg format expressions.
|
//! The format string logic for ucg format expressions.
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::clone::Clone;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
|
|
||||||
@ -22,9 +20,6 @@ use abortable_parser::iter::SliceIter;
|
|||||||
use abortable_parser::Result as ParseResult;
|
use abortable_parser::Result as ParseResult;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::build::assets;
|
|
||||||
use crate::build::{FileBuilder, Val};
|
|
||||||
use crate::error;
|
|
||||||
use crate::iter;
|
use crate::iter;
|
||||||
use crate::parse;
|
use crate::parse;
|
||||||
use crate::tokenizer;
|
use crate::tokenizer;
|
||||||
@ -47,29 +42,13 @@ impl SimpleTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements the logic for format strings in UCG format expressions.
|
|
||||||
pub struct SimpleFormatter<V: Into<String> + Clone> {
|
|
||||||
tmpl: String,
|
|
||||||
args: Vec<V>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: Into<String> + Clone> SimpleFormatter<V> {
|
|
||||||
/// Constructs a Formatter with a template and args.
|
|
||||||
pub fn new<S: Into<String>>(tmpl: S, args: Vec<V>) -> Self {
|
|
||||||
SimpleFormatter {
|
|
||||||
tmpl: tmpl.into(),
|
|
||||||
args: args,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TemplateParser for SimpleTemplate {
|
impl TemplateParser for SimpleTemplate {
|
||||||
fn parse(&self, input: &str) -> TemplateResult {
|
fn parse(&self, input: &str) -> TemplateResult {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut should_escape = false;
|
let mut should_escape = false;
|
||||||
let mut buf: Vec<char> = Vec::new();
|
let mut buf: Vec<char> = Vec::new();
|
||||||
for c in dbg!(input).chars() {
|
for c in input.chars() {
|
||||||
if c == '@' && !should_escape {
|
if c == '@' && !should_escape {
|
||||||
result.push(TemplatePart::Str(buf));
|
result.push(TemplatePart::Str(buf));
|
||||||
buf = Vec::new();
|
buf = Vec::new();
|
||||||
@ -81,7 +60,6 @@ impl TemplateParser for SimpleTemplate {
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
buf.push(c);
|
buf.push(c);
|
||||||
dbg!(&buf);
|
|
||||||
}
|
}
|
||||||
should_escape = false;
|
should_escape = false;
|
||||||
}
|
}
|
||||||
@ -92,59 +70,6 @@ impl TemplateParser for SimpleTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Into<String> + Clone> FormatRenderer for SimpleFormatter<V> {
|
|
||||||
/// Renders a formatter to a string or returns an error.
|
|
||||||
///
|
|
||||||
/// If the formatter has the wrong number of arguments for the number of replacements
|
|
||||||
/// it will return an error. Otherwise it will return the formatted string.
|
|
||||||
fn render(&self, pos: &Position) -> Result<String, Box<dyn Error>> {
|
|
||||||
let mut buf = String::new();
|
|
||||||
let mut count = 0;
|
|
||||||
let parser = SimpleTemplate::new();
|
|
||||||
let parts = parser.parse(&self.tmpl)?;
|
|
||||||
for p in parts {
|
|
||||||
match p {
|
|
||||||
TemplatePart::PlaceHolder(idx) => {
|
|
||||||
if idx == self.args.len() {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
"Too few arguments to string \
|
|
||||||
formatter.",
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
let arg = self.args[count].clone();
|
|
||||||
let strval = arg.into();
|
|
||||||
buf.push_str(&strval);
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
TemplatePart::Str(cs) => {
|
|
||||||
buf.reserve(cs.len());
|
|
||||||
for c in cs {
|
|
||||||
buf.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TemplatePart::Expression(_) => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.args.len() != count {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
format!(
|
|
||||||
"Too many arguments to string \
|
|
||||||
formatter. Expected {} got {}",
|
|
||||||
count,
|
|
||||||
self.args.len()
|
|
||||||
),
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
return Ok(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ExpressionTemplate();
|
pub struct ExpressionTemplate();
|
||||||
|
|
||||||
impl ExpressionTemplate {
|
impl ExpressionTemplate {
|
||||||
@ -226,157 +151,3 @@ impl TemplateParser for ExpressionTemplate {
|
|||||||
Ok(parts)
|
Ok(parts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExpressionFormatter<'a, C>
|
|
||||||
where
|
|
||||||
C: assets::Cache,
|
|
||||||
{
|
|
||||||
tmpl: String,
|
|
||||||
builder: RefCell<FileBuilder<'a, C>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, C> ExpressionFormatter<'a, C>
|
|
||||||
where
|
|
||||||
C: assets::Cache,
|
|
||||||
{
|
|
||||||
pub fn new<S: Into<String>>(tmpl: S, builder: FileBuilder<'a, C>) -> Self {
|
|
||||||
ExpressionFormatter {
|
|
||||||
tmpl: tmpl.into(),
|
|
||||||
builder: RefCell::new(builder),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consume_expr(
|
|
||||||
&self,
|
|
||||||
builder: &mut FileBuilder<'a, C>,
|
|
||||||
iter: &mut Chars,
|
|
||||||
pos: &Position,
|
|
||||||
) -> Result<Val, Box<dyn Error>> {
|
|
||||||
// we expect the next char to be { or we error.
|
|
||||||
let mut expr_string = String::new();
|
|
||||||
let mut brace_count = 0;
|
|
||||||
match iter.next() {
|
|
||||||
Some(c) => {
|
|
||||||
if c == '{' {
|
|
||||||
brace_count += 1;
|
|
||||||
} else {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
format!(
|
|
||||||
"Invalid syntax for format string expected '{{' but got {}",
|
|
||||||
c
|
|
||||||
),
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
"Invalid syntax for format string expected '{' but string ended",
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loop {
|
|
||||||
let c = match iter.next() {
|
|
||||||
Some(c) => c,
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
if c == '{' {
|
|
||||||
brace_count += 1;
|
|
||||||
}
|
|
||||||
if c == '}' {
|
|
||||||
brace_count -= 1;
|
|
||||||
// if brace_count is 0 then this is the end of expression.
|
|
||||||
if brace_count != 0 {
|
|
||||||
// if it is not zero then this character is just part of
|
|
||||||
// the embedded expression.
|
|
||||||
expr_string.push(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// empty expressions are an error
|
|
||||||
if expr_string.is_empty() {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
"Got an empty expression in format string",
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
if !expr_string.ends_with(";") {
|
|
||||||
expr_string.push(';');
|
|
||||||
}
|
|
||||||
// we are done and it is time to compute the expression and return it.
|
|
||||||
return Ok(builder.eval_string(&expr_string)?.as_ref().clone());
|
|
||||||
} else {
|
|
||||||
expr_string.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
"Expected '}' but got end of string",
|
|
||||||
error::ErrorType::FormatError,
|
|
||||||
pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, C> FormatRenderer for ExpressionFormatter<'a, C>
|
|
||||||
where
|
|
||||||
C: assets::Cache,
|
|
||||||
{
|
|
||||||
fn render(&self, pos: &Position) -> Result<String, Box<dyn Error>> {
|
|
||||||
let mut buf = String::new();
|
|
||||||
let mut should_escape = false;
|
|
||||||
let mut iter = self.tmpl.chars();
|
|
||||||
loop {
|
|
||||||
let c = match iter.next() {
|
|
||||||
Some(c) => c,
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
if c == '@' && !should_escape {
|
|
||||||
// This is kind of wasteful. Can we do better?
|
|
||||||
let val = self.consume_expr(&mut self.builder.borrow_mut(), &mut iter, pos)?;
|
|
||||||
let strval: String = val.into();
|
|
||||||
buf.push_str(&strval);
|
|
||||||
should_escape = false;
|
|
||||||
} else if c == '\\' && !should_escape {
|
|
||||||
should_escape = true;
|
|
||||||
} else {
|
|
||||||
buf.push(c);
|
|
||||||
should_escape = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::{FormatRenderer, SimpleFormatter};
|
|
||||||
use crate::ast::Position;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_happy_path() {
|
|
||||||
let formatter = SimpleFormatter::new("foo @ @ \\@", vec!["bar", "quux"]);
|
|
||||||
let pos = Position::new(0, 0, 0);
|
|
||||||
assert_eq!(formatter.render(&pos).unwrap(), "foo bar quux @");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_happy_wrong_too_few_args() {
|
|
||||||
let formatter = SimpleFormatter::new("foo @ @ \\@", vec!["bar"]);
|
|
||||||
let pos = Position::new(0, 0, 0);
|
|
||||||
assert!(formatter.render(&pos).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_happy_wrong_too_many_args() {
|
|
||||||
let formatter = SimpleFormatter::new("foo @ @ \\@", vec!["bar", "quux", "baz"]);
|
|
||||||
let pos = Position::new(0, 0, 0);
|
|
||||||
assert!(formatter.render(&pos).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -20,8 +20,6 @@ pub enum Val {
|
|||||||
List(Vec<Rc<Val>>),
|
List(Vec<Rc<Val>>),
|
||||||
Tuple(Vec<(String, Rc<Val>)>),
|
Tuple(Vec<(String, Rc<Val>)>),
|
||||||
Env(Vec<(String, String)>),
|
Env(Vec<(String, String)>),
|
||||||
Func(FuncDef),
|
|
||||||
Module(ModuleDef),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Val {
|
impl Val {
|
||||||
@ -36,8 +34,6 @@ impl Val {
|
|||||||
&Val::List(_) => "List".to_string(),
|
&Val::List(_) => "List".to_string(),
|
||||||
&Val::Tuple(_) => "Tuple".to_string(),
|
&Val::Tuple(_) => "Tuple".to_string(),
|
||||||
&Val::Env(_) => "Env".to_string(),
|
&Val::Env(_) => "Env".to_string(),
|
||||||
&Val::Func(_) => "Func".to_string(),
|
|
||||||
&Val::Module(_) => "Module".to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +49,7 @@ impl Val {
|
|||||||
&Val::Str(_),
|
&Val::Str(_),
|
||||||
&Val::List(_),
|
&Val::List(_),
|
||||||
&Val::Tuple(_),
|
&Val::Tuple(_),
|
||||||
&Val::Env(_),
|
&Val::Env(_)
|
||||||
&Val::Func(_),
|
|
||||||
&Val::Module(_)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +93,6 @@ impl Val {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new(
|
|
||||||
"Func are not comparable",
|
|
||||||
error::ErrorType::TypeFail,
|
|
||||||
)),
|
|
||||||
(&Val::Module(_), &Val::Module(_)) => Err(error::BuildError::new(
|
|
||||||
"Module are not comparable",
|
|
||||||
error::ErrorType::TypeFail,
|
|
||||||
)),
|
|
||||||
// EMPTY is always comparable for equality.
|
// EMPTY is always comparable for equality.
|
||||||
(&Val::Empty, _) => Ok(false),
|
(&Val::Empty, _) => Ok(false),
|
||||||
(_, &Val::Empty) => Ok(false),
|
(_, &Val::Empty) => Ok(false),
|
||||||
@ -182,25 +168,12 @@ impl Val {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_func(&self) -> bool {
|
|
||||||
if let &Val::Func(_) = self {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_str(&self) -> bool {
|
pub fn is_str(&self) -> bool {
|
||||||
if let &Val::Str(_) = self {
|
if let &Val::Str(_) = self {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pub fn is_module(&self) -> bool {
|
|
||||||
if let &Val::Module(_) = self {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Val {
|
impl Display for Val {
|
||||||
@ -218,8 +191,6 @@ impl Display for Val {
|
|||||||
}
|
}
|
||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
}
|
}
|
||||||
&Val::Func(_) => write!(f, "Func(..)"),
|
|
||||||
&Val::Module(_) => write!(f, "Module{{..}}"),
|
|
||||||
&Val::Tuple(ref def) => {
|
&Val::Tuple(ref def) => {
|
||||||
write!(f, "{{\n")?;
|
write!(f, "{{\n")?;
|
||||||
for v in def.iter() {
|
for v in def.iter() {
|
||||||
|
1979
src/build/mod.rs
1979
src/build/mod.rs
File diff suppressed because it is too large
Load Diff
53
src/build/opcode/debug.rs
Normal file
53
src/build/opcode/debug.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright 2019 Jeremy Wall
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// 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 std::fmt;
|
||||||
|
|
||||||
|
use super::Composite;
|
||||||
|
use super::Primitive;
|
||||||
|
use super::Value;
|
||||||
|
|
||||||
|
use Composite::{List, Tuple};
|
||||||
|
use Primitive::{Bool, Empty, Float, Int, Str};
|
||||||
|
use Value::{C, F, M, P, S, T};
|
||||||
|
|
||||||
|
impl fmt::Debug for Value {
|
||||||
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
P(Bool(v)) => write!(w, "Bool({})", v),
|
||||||
|
P(Int(v)) => write!(w, "Int({})", v),
|
||||||
|
P(Float(v)) => write!(w, "Float({})", v),
|
||||||
|
P(Str(v)) => write!(w, "String({})", v),
|
||||||
|
P(Empty) => write!(w, "NULL"),
|
||||||
|
C(List(ref els)) => {
|
||||||
|
write!(w, "List[")?;
|
||||||
|
for e in els {
|
||||||
|
write!(w, "{:?},", e)?;
|
||||||
|
}
|
||||||
|
write!(w, "]")
|
||||||
|
}
|
||||||
|
C(Tuple(ref flds)) => {
|
||||||
|
write!(w, "Tuple(")?;
|
||||||
|
for (k, v) in flds {
|
||||||
|
write!(w, "\"{}\"={:?},", k, v)?;
|
||||||
|
}
|
||||||
|
write!(w, ")")
|
||||||
|
}
|
||||||
|
F(_) => write!(w, "<Func>"),
|
||||||
|
M(_) => write!(w, "<Module>"),
|
||||||
|
T(_) => write!(w, "<Expression>"),
|
||||||
|
S(v) => write!(w, "Symbol({})", v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,12 +12,18 @@
|
|||||||
// 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 std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io::Write;
|
use std::io::{Write, Read};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use super::pointer::OpPointer;
|
||||||
use super::cache;
|
use super::cache;
|
||||||
use super::Value;
|
use super::Value;
|
||||||
|
use super::Error;
|
||||||
use crate::convert::{ConverterRegistry, ImporterRegistry};
|
use crate::convert::{ConverterRegistry, ImporterRegistry};
|
||||||
|
use crate::iter::OffsetStrIter;
|
||||||
|
use crate::parse::parse;
|
||||||
|
|
||||||
// Shared Environmental between VM's for runtime usage.
|
// Shared Environmental between VM's for runtime usage.
|
||||||
pub struct Environment<Stdout, Stderr>
|
pub struct Environment<Stdout, Stderr>
|
||||||
@ -26,18 +32,23 @@ where
|
|||||||
Stderr: Write,
|
Stderr: Write,
|
||||||
{
|
{
|
||||||
pub val_cache: BTreeMap<String, Rc<Value>>,
|
pub val_cache: BTreeMap<String, Rc<Value>>,
|
||||||
pub op_cache: cache::Ops, // Shared environment
|
pub op_cache: cache::Ops,
|
||||||
pub converter_registry: ConverterRegistry, // Shared environment
|
pub converter_registry: ConverterRegistry,
|
||||||
pub importer_registry: ImporterRegistry, // Shared environment
|
pub importer_registry: ImporterRegistry,
|
||||||
pub stdout: Stdout, // Shared environment
|
pub stdout: Stdout,
|
||||||
pub stderr: Stderr, // Shared environment
|
pub stderr: Stderr,
|
||||||
// TODO(jwall): Environment Variables
|
pub env_vars: BTreeMap<String, String>, // Environment Variables
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
||||||
pub fn new(out: Stdout, err: Stderr) -> Self {
|
pub fn new(out: Stdout, err: Stderr) -> Self {
|
||||||
|
Self::new_with_vars(out, err, BTreeMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_vars(out: Stdout, err: Stderr, vars: BTreeMap<String, String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
val_cache: BTreeMap::new(),
|
val_cache: BTreeMap::new(),
|
||||||
|
env_vars: vars,
|
||||||
op_cache: cache::Ops::new(),
|
op_cache: cache::Ops::new(),
|
||||||
converter_registry: ConverterRegistry::make_registry(),
|
converter_registry: ConverterRegistry::make_registry(),
|
||||||
importer_registry: ImporterRegistry::make_registry(),
|
importer_registry: ImporterRegistry::make_registry(),
|
||||||
@ -45,4 +56,34 @@ impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
|||||||
stderr: err,
|
stderr: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_cached_path_val(&self, path: &String) -> Option<Rc<Value>> {
|
||||||
|
self.val_cache.get(path).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_path_val(&mut self, path: &String, val: Rc<Value>) {
|
||||||
|
self.val_cache.insert(path.clone(), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ops_for_path(&mut self, path: &String) -> Result<OpPointer, Error> {
|
||||||
|
let op_pointer = self.op_cache.entry(path).get_pointer_or_else(
|
||||||
|
|| {
|
||||||
|
// FIXME(jwall): We need to do proper error handling here.
|
||||||
|
let p = PathBuf::from(&path);
|
||||||
|
let root = p.parent().unwrap();
|
||||||
|
// first we read in the file
|
||||||
|
let mut f = File::open(&path).unwrap();
|
||||||
|
// then we parse it
|
||||||
|
let mut contents = String::new();
|
||||||
|
f.read_to_string(&mut contents).unwrap();
|
||||||
|
let iter = OffsetStrIter::new(&contents).with_src_file(&p);
|
||||||
|
let stmts = parse(iter, None).unwrap();
|
||||||
|
// then we create an ops from it
|
||||||
|
let ops = super::translate::AST::translate(stmts, &root);
|
||||||
|
ops
|
||||||
|
},
|
||||||
|
&path,
|
||||||
|
);
|
||||||
|
Ok(op_pointer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
// 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 std::convert::From;
|
use std::convert::From;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::ast::Position;
|
use crate::ast::Position;
|
||||||
|
|
||||||
@ -30,14 +32,32 @@ impl Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> From<E> for Error
|
impl From<regex::Error> for Error {
|
||||||
where
|
fn from(e: regex::Error) -> Self {
|
||||||
E: std::error::Error + Sized,
|
|
||||||
{
|
|
||||||
fn from(e: E) -> Self {
|
|
||||||
Error {
|
Error {
|
||||||
message: e.description().to_owned(),
|
message: format!("{}", e),
|
||||||
pos: None,
|
pos: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(e: std::io::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
message: format!("{}", e),
|
||||||
|
pos: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if let Some(ref pos) = self.pos {
|
||||||
|
write!(f, "{} at {}", self.message, pos)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Error {}
|
@ -15,14 +15,16 @@ use std::convert::{TryFrom, TryInto};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod environment;
|
mod debug;
|
||||||
|
pub mod environment;
|
||||||
mod error;
|
mod error;
|
||||||
pub mod pointer;
|
pub mod pointer;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
mod translate;
|
pub mod translate;
|
||||||
mod vm;
|
mod vm;
|
||||||
|
|
||||||
|
pub use environment::Environment;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use vm::VM;
|
pub use vm::VM;
|
||||||
|
|
||||||
@ -43,6 +45,24 @@ pub enum Primitive {
|
|||||||
|
|
||||||
use Primitive::{Bool, Empty, Float, Int, Str};
|
use Primitive::{Bool, Empty, Float, Int, Str};
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
fn type_name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
P(Int(_)) => "Int",
|
||||||
|
P(Float(_)) => "Float",
|
||||||
|
P(Str(_)) => "String",
|
||||||
|
P(Bool(_)) => "Bool",
|
||||||
|
P(Empty) => "NULL",
|
||||||
|
C(List(_)) => "List",
|
||||||
|
C(Tuple(_)) => "Tuple",
|
||||||
|
F(_) => "Func",
|
||||||
|
M(_) => "Func",
|
||||||
|
T(_) => "Expression",
|
||||||
|
S(_) => "Symbol",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&Primitive> for String {
|
impl From<&Primitive> for String {
|
||||||
fn from(p: &Primitive) -> Self {
|
fn from(p: &Primitive) -> Self {
|
||||||
match p {
|
match p {
|
||||||
@ -107,7 +127,7 @@ pub struct Module {
|
|||||||
pkg_ptr: Option<OpPointer>,
|
pkg_ptr: Option<OpPointer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
// Binding names.
|
// Binding names.
|
||||||
S(String),
|
S(String),
|
||||||
@ -218,29 +238,30 @@ pub enum Op {
|
|||||||
|
|
||||||
use super::ir::Val;
|
use super::ir::Val;
|
||||||
|
|
||||||
impl TryFrom<Rc<Value>> for Val {
|
impl From<Rc<Value>> for Val {
|
||||||
type Error = Error;
|
fn from(val: Rc<Value>) -> Val {
|
||||||
|
val.as_ref().into()
|
||||||
fn try_from(val: Rc<Value>) -> Result<Val, Self::Error> {
|
|
||||||
val.as_ref().try_into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&Value> for Val {
|
impl From<Value> for Val {
|
||||||
type Error = Error;
|
fn from(val: Value) -> Val {
|
||||||
|
(&val).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn try_from(val: &Value) -> Result<Val, Self::Error> {
|
impl From<&Value> for Val {
|
||||||
Ok(match val {
|
fn from(val: &Value) -> Val {
|
||||||
|
match val {
|
||||||
P(Int(i)) => Val::Int(*i),
|
P(Int(i)) => Val::Int(*i),
|
||||||
P(Float(f)) => Val::Float(*f),
|
P(Float(f)) => Val::Float(*f),
|
||||||
P(Str(s)) => Val::Str(s.clone()),
|
P(Str(s)) => Val::Str(s.clone()),
|
||||||
P(Bool(b)) => Val::Boolean(*b),
|
P(Bool(b)) => Val::Boolean(*b),
|
||||||
P(Empty) => Val::Empty,
|
|
||||||
C(Tuple(fs)) => {
|
C(Tuple(fs)) => {
|
||||||
let mut flds = Vec::new();
|
let mut flds = Vec::new();
|
||||||
for &(ref k, ref v) in fs.iter() {
|
for &(ref k, ref v) in fs.iter() {
|
||||||
let v = v.clone();
|
let v = v.clone();
|
||||||
flds.push((k.clone(), Rc::new(v.try_into()?)));
|
flds.push((k.clone(), Rc::new(v.into())));
|
||||||
}
|
}
|
||||||
Val::Tuple(flds)
|
Val::Tuple(flds)
|
||||||
}
|
}
|
||||||
@ -248,33 +269,30 @@ impl TryFrom<&Value> for Val {
|
|||||||
let mut els = Vec::new();
|
let mut els = Vec::new();
|
||||||
for e in elems.iter() {
|
for e in elems.iter() {
|
||||||
let e = e.clone();
|
let e = e.clone();
|
||||||
els.push(Rc::new(e.try_into()?));
|
els.push(Rc::new(e.into()));
|
||||||
}
|
}
|
||||||
Val::List(els)
|
Val::List(els)
|
||||||
}
|
}
|
||||||
S(_) | F(_) | M(_) | T(_) => {
|
S(_) | F(_) | M(_) | T(_) | P(Empty) => Val::Empty,
|
||||||
return Err(dbg!(Error::new(
|
}
|
||||||
format!("Invalid Value {:?} to Val translation", val),
|
|
||||||
Position::new(0, 0, 0)
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Rc<Val>> for Value {
|
impl From<Rc<Val>> for Value {
|
||||||
type Error = Error;
|
fn from(val: Rc<Val>) -> Self {
|
||||||
|
val.as_ref().into()
|
||||||
fn try_from(val: Rc<Val>) -> Result<Self, Self::Error> {
|
|
||||||
val.as_ref().try_into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&Val> for Value {
|
impl From<Val> for Value {
|
||||||
type Error = Error;
|
fn from(val: Val) -> Self {
|
||||||
|
(&val).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn try_from(val: &Val) -> Result<Self, Self::Error> {
|
impl From<&Val> for Value {
|
||||||
Ok(match val {
|
fn from(val: &Val) -> Self {
|
||||||
|
match val {
|
||||||
Val::Int(i) => P(Int(*i)),
|
Val::Int(i) => P(Int(*i)),
|
||||||
Val::Float(f) => P(Float(*f)),
|
Val::Float(f) => P(Float(*f)),
|
||||||
Val::Boolean(b) => P(Bool(*b)),
|
Val::Boolean(b) => P(Bool(*b)),
|
||||||
@ -284,7 +302,7 @@ impl TryFrom<&Val> for Value {
|
|||||||
let mut lst = Vec::new();
|
let mut lst = Vec::new();
|
||||||
for e in els.iter() {
|
for e in els.iter() {
|
||||||
let e = e.clone();
|
let e = e.clone();
|
||||||
lst.push(Rc::new(e.try_into()?));
|
lst.push(Rc::new(e.into()));
|
||||||
}
|
}
|
||||||
C(List(lst))
|
C(List(lst))
|
||||||
}
|
}
|
||||||
@ -292,7 +310,7 @@ impl TryFrom<&Val> for Value {
|
|||||||
let mut field_list = Vec::new();
|
let mut field_list = Vec::new();
|
||||||
for &(ref key, ref val) in flds.iter() {
|
for &(ref key, ref val) in flds.iter() {
|
||||||
let val = val.clone();
|
let val = val.clone();
|
||||||
field_list.push((key.clone(), Rc::new(val.try_into()?)));
|
field_list.push((key.clone(), Rc::new(val.into())));
|
||||||
}
|
}
|
||||||
C(Tuple(field_list))
|
C(Tuple(field_list))
|
||||||
}
|
}
|
||||||
@ -303,15 +321,7 @@ impl TryFrom<&Val> for Value {
|
|||||||
}
|
}
|
||||||
C(Tuple(field_list))
|
C(Tuple(field_list))
|
||||||
}
|
}
|
||||||
// TODO(jwall): These can go away eventually when we replace the tree
|
}
|
||||||
// walking interpreter.
|
|
||||||
Val::Module(_) | Val::Func(_) => {
|
|
||||||
return Err(dbg!(Error::new(
|
|
||||||
format!("Invalid Translation from Val {} to Value", val),
|
|
||||||
Position::new(0, 0, 0)
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,13 +60,13 @@ impl OpPointer {
|
|||||||
self.ptr = Some(ptr);
|
self.ptr = Some(ptr);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Err(dbg!(Error::new(
|
Err(Error::new(
|
||||||
format!("FAULT!!! Invalid Jump!"),
|
format!("FAULT!!! Invalid Jump!"),
|
||||||
match self.pos() {
|
match self.pos() {
|
||||||
Some(pos) => pos.clone(),
|
Some(pos) => pos.clone(),
|
||||||
None => Position::new(0, 0, 0),
|
None => Position::new(0, 0, 0),
|
||||||
},
|
},
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn op(&self) -> Option<&Op> {
|
pub fn op(&self) -> Option<&Op> {
|
||||||
@ -86,10 +86,10 @@ impl OpPointer {
|
|||||||
pub fn idx(&self) -> Result<usize, Error> {
|
pub fn idx(&self) -> Result<usize, Error> {
|
||||||
match self.ptr {
|
match self.ptr {
|
||||||
Some(ptr) => Ok(ptr),
|
Some(ptr) => Ok(ptr),
|
||||||
None => dbg!(Err(Error::new(
|
None => Err(Error::new(
|
||||||
format!("FAULT!!! Position Check failure!"),
|
format!("FAULT!!! Position Check failure!"),
|
||||||
Position::new(0, 0, 0),
|
Position::new(0, 0, 0),
|
||||||
))),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
// 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 std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::convert::{TryFrom, TryInto};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -27,8 +26,6 @@ use super::{Composite, Error, Hook, Primitive, Value};
|
|||||||
use crate::ast::Position;
|
use crate::ast::Position;
|
||||||
use crate::build::ir::Val;
|
use crate::build::ir::Val;
|
||||||
use crate::build::AssertCollector;
|
use crate::build::AssertCollector;
|
||||||
use crate::iter::OffsetStrIter;
|
|
||||||
use crate::parse::parse;
|
|
||||||
use Composite::{List, Tuple};
|
use Composite::{List, Tuple};
|
||||||
use Primitive::{Bool, Empty, Int, Str};
|
use Primitive::{Bool, Empty, Int, Str};
|
||||||
|
|
||||||
@ -36,6 +33,7 @@ pub struct Builtins {
|
|||||||
assert_results: AssertCollector,
|
assert_results: AssertCollector,
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
import_path: Vec<PathBuf>,
|
import_path: Vec<PathBuf>,
|
||||||
|
validate_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builtins {
|
impl Builtins {
|
||||||
@ -47,7 +45,9 @@ impl Builtins {
|
|||||||
Self {
|
Self {
|
||||||
assert_results: AssertCollector::new(),
|
assert_results: AssertCollector::new(),
|
||||||
working_dir: path.into(),
|
working_dir: path.into(),
|
||||||
|
// FIXME(jwall): This should probably be injected in.
|
||||||
import_path: Vec::new(),
|
import_path: Vec::new(),
|
||||||
|
validate_mode: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +56,14 @@ impl Builtins {
|
|||||||
assert_results: AssertCollector::new(),
|
assert_results: AssertCollector::new(),
|
||||||
working_dir: self.working_dir.clone(),
|
working_dir: self.working_dir.clone(),
|
||||||
import_path: self.import_path.clone(),
|
import_path: self.import_path.clone(),
|
||||||
|
validate_mode: self.validate_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_validate_mode(&mut self) {
|
||||||
|
self.validate_mode = true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle<P: AsRef<Path>, O, E>(
|
pub fn handle<P: AsRef<Path>, O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: Option<P>,
|
path: Option<P>,
|
||||||
@ -115,10 +120,10 @@ impl Builtins {
|
|||||||
}
|
}
|
||||||
match normalized.canonicalize() {
|
match normalized.canonicalize() {
|
||||||
Ok(p) => Ok(p),
|
Ok(p) => Ok(p),
|
||||||
Err(_e) => Err(dbg!(Error::new(
|
Err(_e) => Err(Error::new(
|
||||||
format!("Invalid path: {}", normalized.to_string_lossy()),
|
format!("Invalid path: {}", normalized.to_string_lossy()),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
))),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +139,14 @@ impl Builtins {
|
|||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(jwall): Should probably move this to the runtime.
|
||||||
|
//fn detect_import_cycle(&self, path: &str) -> bool {
|
||||||
|
// self.scope
|
||||||
|
// .import_stack
|
||||||
|
// .iter()
|
||||||
|
// .find(|p| *p == path)
|
||||||
|
// .is_some()
|
||||||
|
//}
|
||||||
fn import<O, E>(
|
fn import<O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
@ -148,37 +161,22 @@ impl Builtins {
|
|||||||
if let Some((val, path_pos)) = path {
|
if let Some((val, path_pos)) = path {
|
||||||
if let &Value::P(Str(ref path)) = val.as_ref() {
|
if let &Value::P(Str(ref path)) = val.as_ref() {
|
||||||
let mut borrowed_env = env.borrow_mut();
|
let mut borrowed_env = env.borrow_mut();
|
||||||
let val_cache = &mut borrowed_env.val_cache;
|
match borrowed_env.get_cached_path_val(path) {
|
||||||
if val_cache.contains_key(path) {
|
Some(v) => {
|
||||||
stack.push((val_cache[path].clone(), path_pos));
|
stack.push((v, path_pos));
|
||||||
} else {
|
}
|
||||||
let op_pointer = env.borrow_mut().op_cache.entry(path).get_pointer_or_else(
|
None => {
|
||||||
|| {
|
let op_pointer = borrowed_env.get_ops_for_path(path)?;
|
||||||
// FIXME(jwall): We need to do proper error handling here.
|
let mut vm = VM::with_pointer(op_pointer, env.clone());
|
||||||
let p = PathBuf::from(&path);
|
vm.run()?;
|
||||||
let root = p.parent().unwrap();
|
let result = Rc::new(vm.symbols_to_tuple(true));
|
||||||
// first we read in the file
|
borrowed_env.update_path_val(&path, result.clone());
|
||||||
let mut f = File::open(&path).unwrap();
|
stack.push((result, pos));
|
||||||
// then we parse it
|
}
|
||||||
let mut contents = String::new();
|
|
||||||
f.read_to_string(&mut contents).unwrap();
|
|
||||||
let iter = OffsetStrIter::new(&contents).with_src_file(&p);
|
|
||||||
let stmts = parse(iter, None).unwrap();
|
|
||||||
// then we create an ops from it
|
|
||||||
let ops = super::translate::AST::translate(stmts, &root);
|
|
||||||
ops
|
|
||||||
},
|
|
||||||
&path,
|
|
||||||
);
|
|
||||||
let mut vm = VM::with_pointer(op_pointer, env.clone());
|
|
||||||
vm.run()?;
|
|
||||||
let result = Rc::new(vm.symbols_to_tuple(true));
|
|
||||||
val_cache.insert(path.clone(), result.clone());
|
|
||||||
stack.push((result, pos));
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(format!("Invalid Path {:?}", val), pos,)));
|
return Err(Error::new(format!("Invalid Path {:?}", val), pos));
|
||||||
}
|
}
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@ -199,10 +197,7 @@ impl Builtins {
|
|||||||
if let &Value::P(Str(ref path)) = val.as_ref() {
|
if let &Value::P(Str(ref path)) = val.as_ref() {
|
||||||
path.clone()
|
path.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(format!("Invalid Path {:?}", val), path_pos));
|
||||||
format!("Invalid Path {:?}", val),
|
|
||||||
path_pos,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -211,10 +206,10 @@ impl Builtins {
|
|||||||
if let &Value::P(Str(ref typ)) = val.as_ref() {
|
if let &Value::P(Str(ref typ)) = val.as_ref() {
|
||||||
typ.clone()
|
typ.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected conversion type but got {:?}", val),
|
format!("Expected conversion type but got {:?}", val),
|
||||||
typ_pos,
|
typ_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -234,16 +229,13 @@ impl Builtins {
|
|||||||
P(Empty)
|
P(Empty)
|
||||||
} else {
|
} else {
|
||||||
match importer.import(contents.as_bytes()) {
|
match importer.import(contents.as_bytes()) {
|
||||||
Ok(v) => v.try_into()?,
|
Ok(v) => v.into(),
|
||||||
Err(e) => return Err(dbg!(Error::new(format!("{}", e), pos,))),
|
Err(e) => return Err(Error::new(format!("{}", e), pos)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(format!("No such conversion type {}", &typ), pos))
|
||||||
format!("No such conversion type {}", &typ),
|
|
||||||
pos,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
pos,
|
pos,
|
||||||
@ -306,26 +298,26 @@ impl Builtins {
|
|||||||
};
|
};
|
||||||
let val = stack.pop();
|
let val = stack.pop();
|
||||||
if let Some((val, val_pos)) = val {
|
if let Some((val, val_pos)) = val {
|
||||||
let val = val.try_into()?;
|
let val = val.into();
|
||||||
let c_type = stack.pop();
|
let c_type = stack.pop();
|
||||||
if let Some((c_type_val, c_type_pos)) = c_type {
|
if let Some((c_type_val, c_type_pos)) = c_type {
|
||||||
if let &Value::S(ref c_type) = c_type_val.as_ref() {
|
if let &Value::S(ref c_type) = c_type_val.as_ref() {
|
||||||
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
||||||
if let Err(e) = c.convert(Rc::new(val), &mut writer) {
|
if let Err(e) = c.convert(Rc::new(val), &mut writer) {
|
||||||
return Err(dbg!(Error::new(format!("{}", e), pos.clone(),)));
|
return Err(Error::new(format!("{}", e), pos.clone()));
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("No such conversion type {:?}", c_type),
|
format!("No such conversion type {:?}", c_type),
|
||||||
c_type_pos,
|
c_type_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Not a conversion type {:?}", c_type_val),
|
format!("Not a conversion type {:?}", c_type_val),
|
||||||
val_pos,
|
val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -343,7 +335,7 @@ impl Builtins {
|
|||||||
{
|
{
|
||||||
let val = stack.pop();
|
let val = stack.pop();
|
||||||
if let Some((val, val_pos)) = val {
|
if let Some((val, val_pos)) = val {
|
||||||
let val = val.try_into()?;
|
let val = val.into();
|
||||||
if let Some((c_type_val, c_typ_pos)) = stack.pop() {
|
if let Some((c_type_val, c_typ_pos)) = stack.pop() {
|
||||||
if let &Value::S(ref c_type) = c_type_val.as_ref() {
|
if let &Value::S(ref c_type) = c_type_val.as_ref() {
|
||||||
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
||||||
@ -358,20 +350,20 @@ impl Builtins {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("No such conversion type {:?}", c_type),
|
format!("No such conversion type {:?}", c_type),
|
||||||
c_typ_pos,
|
c_typ_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Not a conversion type {:?}", val),
|
format!("Not a conversion type {:?}", val),
|
||||||
val_pos,
|
val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -402,7 +394,7 @@ impl Builtins {
|
|||||||
let f = if let &F(ref f) = fptr.as_ref() {
|
let f = if let &F(ref f) = fptr.as_ref() {
|
||||||
f
|
f
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(format!("Not a function!!"), fptr_pos)));
|
return Err(Error::new(format!("Not a function!!"), fptr_pos));
|
||||||
};
|
};
|
||||||
|
|
||||||
match list.as_ref() {
|
match list.as_ref() {
|
||||||
@ -426,24 +418,24 @@ impl Builtins {
|
|||||||
if let &C(List(ref fval)) = result.as_ref() {
|
if let &C(List(ref fval)) = result.as_ref() {
|
||||||
// we expect them to be a list of exactly 2 items.
|
// we expect them to be a list of exactly 2 items.
|
||||||
if fval.len() != 2 {
|
if fval.len() != 2 {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Map Functions over tuples must return a list of two items"
|
"Map Functions over tuples must return a list of two items"
|
||||||
),
|
),
|
||||||
result_pos,
|
result_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
let name = match fval[0].as_ref() {
|
let name = match fval[0].as_ref() {
|
||||||
&P(Str(ref name)) => name.clone(),
|
&P(Str(ref name)) => name.clone(),
|
||||||
_ => return Err(dbg!(Error::new(
|
_ => return Err(Error::new(
|
||||||
format!("Map functions over tuples must return a String as the first list item"),
|
format!("Map functions over tuples must return a String as the first list item"),
|
||||||
result_pos,
|
result_pos,
|
||||||
))),
|
)),
|
||||||
};
|
};
|
||||||
new_fields.push((name, fval[1].clone()));
|
new_fields.push((name, fval[1].clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack.push((Rc::new(C(Tuple(dbg!(new_fields)))), pos));
|
stack.push((Rc::new(C(Tuple(new_fields))), pos));
|
||||||
}
|
}
|
||||||
&P(Str(ref s)) => {
|
&P(Str(ref s)) => {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -454,19 +446,19 @@ impl Builtins {
|
|||||||
if let &P(Str(ref s)) = result.as_ref() {
|
if let &P(Str(ref s)) = result.as_ref() {
|
||||||
buf.push_str(s);
|
buf.push_str(s);
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Map functions over string should return strings"),
|
format!("Map functions over string should return strings"),
|
||||||
result_pos
|
result_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack.push((Rc::new(P(Str(buf))), pos));
|
stack.push((Rc::new(P(Str(buf))), pos));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("You can only map over lists, tuples, or strings"),
|
format!("You can only map over lists, tuples, or strings"),
|
||||||
pos,
|
pos,
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -498,7 +490,7 @@ impl Builtins {
|
|||||||
let f = if let &F(ref f) = fptr.as_ref() {
|
let f = if let &F(ref f) = fptr.as_ref() {
|
||||||
f
|
f
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(format!("Not a function!!"), fptr_pos)));
|
return Err(Error::new(format!("Not a function!!"), fptr_pos));
|
||||||
};
|
};
|
||||||
|
|
||||||
match list.as_ref() {
|
match list.as_ref() {
|
||||||
@ -535,7 +527,7 @@ impl Builtins {
|
|||||||
_ => new_fields.push((name.clone(), val.clone())),
|
_ => new_fields.push((name.clone(), val.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack.push((Rc::new(C(Tuple(dbg!(new_fields)))), pos));
|
stack.push((Rc::new(C(Tuple(new_fields))), pos));
|
||||||
}
|
}
|
||||||
&P(Str(ref s)) => {
|
&P(Str(ref s)) => {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -555,10 +547,10 @@ impl Builtins {
|
|||||||
stack.push((Rc::new(P(Str(buf))), pos));
|
stack.push((Rc::new(P(Str(buf))), pos));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("You can only filter over lists, tuples, or strings"),
|
format!("You can only filter over lists, tuples, or strings"),
|
||||||
pos,
|
pos,
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -570,10 +562,10 @@ impl Builtins {
|
|||||||
if let &P(Str(ref s)) = val.as_ref() {
|
if let &P(Str(ref s)) = val.as_ref() {
|
||||||
s.clone()
|
s.clone()
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected string bug got {:?}", val),
|
format!("Expected string bug got {:?}", val),
|
||||||
val_pos,
|
val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -584,10 +576,10 @@ impl Builtins {
|
|||||||
if let &P(Str(ref s)) = val.as_ref() {
|
if let &P(Str(ref s)) = val.as_ref() {
|
||||||
s.clone()
|
s.clone()
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected string bug got {:?}", val),
|
format!("Expected string bug got {:?}", val),
|
||||||
val_pos,
|
val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -631,15 +623,15 @@ impl Builtins {
|
|||||||
let f = if let &F(ref f) = fptr.as_ref() {
|
let f = if let &F(ref f) = fptr.as_ref() {
|
||||||
f
|
f
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(format!("Not a function!"), fptr_pos)));
|
return Err(Error::new(format!("Not a function!"), fptr_pos));
|
||||||
};
|
};
|
||||||
|
|
||||||
match list.as_ref() {
|
match list.as_ref() {
|
||||||
&C(List(ref elems)) => {
|
&C(List(ref elems)) => {
|
||||||
for e in dbg!(elems).iter() {
|
for e in elems.iter() {
|
||||||
// push function arguments on the stack.
|
// push function arguments on the stack.
|
||||||
stack.push((dbg!(e.clone()), list_pos.clone()));
|
stack.push((e.clone(), list_pos.clone()));
|
||||||
stack.push((dbg!(acc.clone()), acc_pos.clone()));
|
stack.push((acc.clone(), acc_pos.clone()));
|
||||||
// call function and push it's result on the stack.
|
// call function and push it's result on the stack.
|
||||||
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
||||||
acc = new_acc;
|
acc = new_acc;
|
||||||
@ -651,7 +643,7 @@ impl Builtins {
|
|||||||
// push function arguments on the stack.
|
// push function arguments on the stack.
|
||||||
stack.push((val.clone(), list_pos.clone()));
|
stack.push((val.clone(), list_pos.clone()));
|
||||||
stack.push((Rc::new(P(Str(name.clone()))), list_pos.clone()));
|
stack.push((Rc::new(P(Str(name.clone()))), list_pos.clone()));
|
||||||
stack.push((dbg!(acc.clone()), acc_pos.clone()));
|
stack.push((acc.clone(), acc_pos.clone()));
|
||||||
// call function and push it's result on the stack.
|
// call function and push it's result on the stack.
|
||||||
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
||||||
acc = new_acc;
|
acc = new_acc;
|
||||||
@ -661,8 +653,8 @@ impl Builtins {
|
|||||||
&P(Str(ref _s)) => {
|
&P(Str(ref _s)) => {
|
||||||
for c in _s.chars() {
|
for c in _s.chars() {
|
||||||
// push function arguments on the stack.
|
// push function arguments on the stack.
|
||||||
stack.push((dbg!(Rc::new(P(Str(c.to_string())))), list_pos.clone()));
|
stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone()));
|
||||||
stack.push((dbg!(acc.clone()), acc_pos.clone()));
|
stack.push((acc.clone(), acc_pos.clone()));
|
||||||
// call function and push it's result on the stack.
|
// call function and push it's result on the stack.
|
||||||
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone())?;
|
||||||
acc = new_acc;
|
acc = new_acc;
|
||||||
@ -670,15 +662,15 @@ impl Builtins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("You can only reduce over lists, tuples, or strings"),
|
format!("You can only reduce over lists, tuples, or strings"),
|
||||||
pos.clone()
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// push the acc on the stack as our result
|
// push the acc on the stack as our result
|
||||||
stack.push((dbg!(acc), pos));
|
stack.push((acc, pos));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,10 +708,10 @@ impl Builtins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Ranges can only be created with Ints"),
|
format!("Ranges can only be created with Ints"),
|
||||||
pos,
|
pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack.push((Rc::new(C(List(elems))), pos));
|
stack.push((Rc::new(C(List(elems))), pos));
|
||||||
@ -736,20 +728,20 @@ impl Builtins {
|
|||||||
O: std::io::Write,
|
O: std::io::Write,
|
||||||
E: std::io::Write,
|
E: std::io::Write,
|
||||||
{
|
{
|
||||||
let (val, val_pos) = if let Some(val) = dbg!(stack.pop()) {
|
let (val, val_pos) = if let Some(val) = stack.pop() {
|
||||||
val
|
val
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
let expr = stack.pop();
|
let expr = stack.pop();
|
||||||
let expr_pretty = match expr {
|
let expr_pretty = match expr {
|
||||||
Some((ref expr, _)) => match dbg!(expr.as_ref()) {
|
Some((ref expr, _)) => match expr.as_ref() {
|
||||||
&P(Str(ref expr)) => expr.clone(),
|
&P(Str(ref expr)) => expr.clone(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let writable_val: Val = TryFrom::try_from(val.clone())?;
|
let writable_val: Val = val.clone().into();
|
||||||
if let Err(e) = writeln!(
|
if let Err(e) = writeln!(
|
||||||
&mut env.borrow_mut().stderr,
|
&mut env.borrow_mut().stderr,
|
||||||
"TRACE: {} = {} at {}",
|
"TRACE: {} = {} at {}",
|
||||||
@ -757,7 +749,7 @@ impl Builtins {
|
|||||||
writable_val,
|
writable_val,
|
||||||
&val_pos
|
&val_pos
|
||||||
) {
|
) {
|
||||||
return Err(dbg!(Error::new(format!("{}", e), pos)));
|
return Err(Error::new(format!("{}", e), pos));
|
||||||
};
|
};
|
||||||
stack.push((val, val_pos));
|
stack.push((val, val_pos));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -41,7 +41,7 @@ macro_rules! assert_cases {
|
|||||||
};
|
};
|
||||||
let mut vm = VM::new(Rc::new(map), env);
|
let mut vm = VM::new(Rc::new(map), env);
|
||||||
vm.run().unwrap();
|
vm.run().unwrap();
|
||||||
assert_eq!(dbg!(vm.pop()).unwrap().0, Rc::new(case.1));
|
assert_eq!(vm.pop().unwrap().0, Rc::new(case.1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -792,9 +792,30 @@ fn simple_selects() {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn select_fails() {
|
||||||
|
assert_parse_cases![
|
||||||
|
"select \"quux\", { foo = 1, bar = 2, };" => P(Int(1)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_compound_expressions() {
|
||||||
|
assert_parse_cases![
|
||||||
|
"select \"foo\", { foo = 1, bar = 2, } == 1;" => P(Bool(true)),
|
||||||
|
"select \"foo\", { foo = 1, bar = 2, } == 2;" => P(Bool(false)),
|
||||||
|
"select \"foo\", 3, { foo = 1, bar = 2, } == 2;" => P(Bool(false)),
|
||||||
|
"select \"quux\", 3, { foo = 1, bar = 2, } == 3;" => P(Bool(true)),
|
||||||
|
"let want = \"foo\"; select want, { foo = 1, bar = 2, } == 1;" => P(Bool(true)),
|
||||||
|
"let want = \"foo\"; select want, 3, { foo = 1, bar = 2, } == 1;" => P(Bool(true)),
|
||||||
|
"{ok = select \"foo\", { foo = 1, bar = 2, } == 2}.ok;" => P(Bool(false)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_trace() {
|
fn simple_trace() {
|
||||||
let stmts = parse(OffsetStrIter::from(dbg!("TRACE 1+1;")), None).unwrap();
|
let stmts = parse(OffsetStrIter::from("TRACE 1+1;"), None).unwrap();
|
||||||
let root = std::env::current_dir().unwrap();
|
let root = std::env::current_dir().unwrap();
|
||||||
let ops = Rc::new(translate::AST::translate(stmts, &root));
|
let ops = Rc::new(translate::AST::translate(stmts, &root));
|
||||||
assert!(ops.len() > 0);
|
assert!(ops.len() > 0);
|
||||||
|
@ -52,36 +52,40 @@ impl AST {
|
|||||||
return ops;
|
return ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn translate_stmt(stmt: Statement, mut ops: &mut PositionMap, root: &Path) {
|
||||||
|
match stmt {
|
||||||
|
Statement::Expression(expr) => {
|
||||||
|
let expr_pos = expr.pos().clone();
|
||||||
|
Self::translate_expr(expr, &mut ops, root);
|
||||||
|
ops.push(Op::Pop, expr_pos);
|
||||||
|
}
|
||||||
|
Statement::Assert(pos, expr) => {
|
||||||
|
Self::translate_expr(expr, &mut ops, root);
|
||||||
|
ops.push(Op::Runtime(Hook::Assert), pos);
|
||||||
|
}
|
||||||
|
Statement::Let(def) => {
|
||||||
|
let binding = def.name.fragment;
|
||||||
|
ops.push(Op::Sym(binding), def.name.pos);
|
||||||
|
Self::translate_expr(def.value, &mut ops, root);
|
||||||
|
ops.push(Op::Bind, def.pos);
|
||||||
|
}
|
||||||
|
Statement::Output(pos, tok, expr) => {
|
||||||
|
ops.push(Op::Val(Primitive::Str(tok.fragment)), tok.pos);
|
||||||
|
Self::translate_expr(expr, &mut ops, root);
|
||||||
|
ops.push(Op::Runtime(Hook::Out), pos);
|
||||||
|
}
|
||||||
|
Statement::Print(pos, tok, expr) => {
|
||||||
|
ops.push(Op::Val(Primitive::Str(tok.fragment)), tok.pos);
|
||||||
|
Self::translate_expr(expr, &mut ops, root);
|
||||||
|
ops.push(Op::Runtime(Hook::Convert), pos.clone());
|
||||||
|
ops.push(Op::Pop, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut PositionMap, root: &Path) {
|
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut PositionMap, root: &Path) {
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
match stmt {
|
Self::translate_stmt(stmt, &mut ops, root);
|
||||||
Statement::Expression(expr) => {
|
|
||||||
let expr_pos = expr.pos().clone();
|
|
||||||
Self::translate_expr(expr, &mut ops, root);
|
|
||||||
ops.push(Op::Pop, expr_pos);
|
|
||||||
}
|
|
||||||
Statement::Assert(pos, expr) => {
|
|
||||||
Self::translate_expr(expr, &mut ops, root);
|
|
||||||
ops.push(Op::Runtime(Hook::Assert), pos);
|
|
||||||
}
|
|
||||||
Statement::Let(def) => {
|
|
||||||
let binding = def.name.fragment;
|
|
||||||
ops.push(Op::Sym(binding), def.name.pos);
|
|
||||||
Self::translate_expr(def.value, &mut ops, root);
|
|
||||||
ops.push(Op::Bind, def.pos);
|
|
||||||
}
|
|
||||||
Statement::Output(pos, tok, expr) => {
|
|
||||||
ops.push(Op::Val(Primitive::Str(tok.fragment)), tok.pos);
|
|
||||||
Self::translate_expr(expr, &mut ops, root);
|
|
||||||
ops.push(Op::Runtime(Hook::Out), pos);
|
|
||||||
}
|
|
||||||
Statement::Print(pos, tok, expr) => {
|
|
||||||
ops.push(Op::Val(Primitive::Str(tok.fragment)), tok.pos);
|
|
||||||
Self::translate_expr(expr, &mut ops, root);
|
|
||||||
ops.push(Op::Runtime(Hook::Convert), pos.clone());
|
|
||||||
ops.push(Op::Pop, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +170,7 @@ impl AST {
|
|||||||
let idx = ops.len() - 1;
|
let idx = ops.len() - 1;
|
||||||
Self::translate_expr(*def.right, &mut ops, root);
|
Self::translate_expr(*def.right, &mut ops, root);
|
||||||
let jptr = (ops.len() - 1 - idx) as i32;
|
let jptr = (ops.len() - 1 - idx) as i32;
|
||||||
ops.replace(idx, Op::And(dbg!(jptr)));
|
ops.replace(idx, Op::And(jptr));
|
||||||
}
|
}
|
||||||
BinaryExprType::OR => {
|
BinaryExprType::OR => {
|
||||||
Self::translate_expr(*def.left, &mut ops, root);
|
Self::translate_expr(*def.left, &mut ops, root);
|
||||||
@ -174,7 +178,7 @@ impl AST {
|
|||||||
let idx = ops.len() - 1;
|
let idx = ops.len() - 1;
|
||||||
Self::translate_expr(*def.right, &mut ops, root);
|
Self::translate_expr(*def.right, &mut ops, root);
|
||||||
let jptr = (ops.len() - 1 - idx) as i32;
|
let jptr = (ops.len() - 1 - idx) as i32;
|
||||||
ops.replace(idx, Op::Or(dbg!(jptr)));
|
ops.replace(idx, Op::Or(jptr));
|
||||||
}
|
}
|
||||||
BinaryExprType::Mod => {
|
BinaryExprType::Mod => {
|
||||||
Self::translate_expr(*def.right, &mut ops, root);
|
Self::translate_expr(*def.right, &mut ops, root);
|
||||||
@ -208,7 +212,7 @@ impl AST {
|
|||||||
Self::translate_expr(*def.left, &mut ops, root);
|
Self::translate_expr(*def.left, &mut ops, root);
|
||||||
// Symbols on the right side should be converted to strings to satisfy
|
// Symbols on the right side should be converted to strings to satisfy
|
||||||
// the Index operation contract.
|
// the Index operation contract.
|
||||||
match dbg!(*def.right) {
|
match *def.right {
|
||||||
Expression::Copy(copy_def) => {
|
Expression::Copy(copy_def) => {
|
||||||
// first handle the selector
|
// first handle the selector
|
||||||
match copy_def.selector {
|
match copy_def.selector {
|
||||||
@ -460,16 +464,16 @@ impl AST {
|
|||||||
ops.replace(idx, Op::SelectJump(jptr as i32));
|
ops.replace(idx, Op::SelectJump(jptr as i32));
|
||||||
}
|
}
|
||||||
ops.push(Op::Pop, def.pos.clone());
|
ops.push(Op::Pop, def.pos.clone());
|
||||||
let end = ops.len() - 1;
|
|
||||||
for i in jumps {
|
|
||||||
let idx = end - i;
|
|
||||||
ops.replace(i, Op::Jump(idx as i32));
|
|
||||||
}
|
|
||||||
if let Some(default) = def.default {
|
if let Some(default) = def.default {
|
||||||
Self::translate_expr(*default, &mut ops, root);
|
Self::translate_expr(*default, &mut ops, root);
|
||||||
} else {
|
} else {
|
||||||
ops.push(Op::Bang, def.pos);
|
ops.push(Op::Bang, def.pos);
|
||||||
}
|
}
|
||||||
|
let end = ops.len() - 1;
|
||||||
|
for i in jumps {
|
||||||
|
let idx = end - i;
|
||||||
|
ops.replace(i, Op::Jump(idx as i32));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expression::Call(def) => {
|
Expression::Call(def) => {
|
||||||
// first push our arguments.
|
// first push our arguments.
|
||||||
|
@ -77,6 +77,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_validate_mode(&mut self) {
|
||||||
|
self.runtime.enable_validate_mode();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_scoped(self, symbols: Stack) -> Self {
|
pub fn to_scoped(self, symbols: Stack) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
@ -153,7 +157,7 @@ where
|
|||||||
Op::FCall => self.op_fcall(pos)?,
|
Op::FCall => self.op_fcall(pos)?,
|
||||||
Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?,
|
Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?,
|
||||||
Op::Return => {
|
Op::Return => {
|
||||||
dbg!(&self.stack);
|
&self.stack;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Op::Pop => {
|
Op::Pop => {
|
||||||
@ -213,33 +217,33 @@ where
|
|||||||
self.op_jump(jp)?;
|
self.op_jump(jp)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Not a boolean condition {:?} in && expression at {}",
|
"Not a boolean condition {:?} in && expression at {}",
|
||||||
cond, pos
|
cond, pos
|
||||||
),
|
),
|
||||||
cond_pos.clone(),
|
cond_pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_or(&mut self, jp: i32, pos: Position) -> Result<(), Error> {
|
fn op_or(&mut self, jp: i32, pos: Position) -> Result<(), Error> {
|
||||||
let (cond, cond_pos) = self.pop()?;
|
let (cond, cond_pos) = self.pop()?;
|
||||||
let cc = dbg!(cond.clone());
|
let cc = cond.clone();
|
||||||
if let &P(Bool(cond)) = cond.as_ref() {
|
if let &P(Bool(cond)) = cond.as_ref() {
|
||||||
if dbg!(cond) {
|
if cond {
|
||||||
self.push(cc, cond_pos)?;
|
self.push(cc, cond_pos)?;
|
||||||
self.op_jump(jp)?;
|
self.op_jump(jp)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Not a boolean condition {:?} in || expression at {}!",
|
"Not a boolean condition {:?} in || expression at {}!",
|
||||||
cond, pos
|
cond, pos
|
||||||
),
|
),
|
||||||
cond_pos.clone(),
|
cond_pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -251,10 +255,10 @@ where
|
|||||||
self.op_jump(jp)?;
|
self.op_jump(jp)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected boolean but got {:?}!", cond),
|
format!("Expected boolean but got {:?}!", cond),
|
||||||
cond_pos.clone(),
|
cond_pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -266,19 +270,19 @@ where
|
|||||||
self.op_jump(jp)?;
|
self.op_jump(jp)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected boolean but got {:?}!", cond),
|
format!("Expected boolean but got {:?}!", cond),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_select_jump(&'a mut self, jp: i32) -> Result<(), Error> {
|
fn op_select_jump(&'a mut self, jp: i32) -> Result<(), Error> {
|
||||||
// pop field value off
|
// pop field value off
|
||||||
let (field_name, _) = dbg!(self.pop())?;
|
let (field_name, _) = self.pop()?;
|
||||||
// pop search value off
|
// pop search value off
|
||||||
let (search, srch_pos) = dbg!(self.pop())?;
|
let (search, srch_pos) = self.pop()?;
|
||||||
// compare them.
|
// compare them.
|
||||||
let matched = match (field_name.as_ref(), search.as_ref()) {
|
let matched = match (field_name.as_ref(), search.as_ref()) {
|
||||||
(&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname,
|
(&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname,
|
||||||
@ -286,14 +290,14 @@ where
|
|||||||
};
|
};
|
||||||
if !matched {
|
if !matched {
|
||||||
// if they aren't equal then push search value back on and jump
|
// if they aren't equal then push search value back on and jump
|
||||||
self.push(dbg!(search), srch_pos)?;
|
self.push(search, srch_pos)?;
|
||||||
self.op_jump(dbg!(jp))?;
|
self.op_jump(jp)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_module(&'a mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
|
fn op_module(&'a mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
|
||||||
let (mod_val, mod_val_pos) = dbg!(self.pop())?;
|
let (mod_val, mod_val_pos) = self.pop()?;
|
||||||
let (result_ptr, flds) = match mod_val.as_ref() {
|
let (result_ptr, flds) = match mod_val.as_ref() {
|
||||||
&C(Tuple(ref flds)) => (None, flds.clone()),
|
&C(Tuple(ref flds)) => (None, flds.clone()),
|
||||||
&T(ptr) => {
|
&T(ptr) => {
|
||||||
@ -301,17 +305,17 @@ where
|
|||||||
if let &C(Tuple(ref flds)) = tpl_val.as_ref() {
|
if let &C(Tuple(ref flds)) = tpl_val.as_ref() {
|
||||||
(Some(ptr), flds.clone())
|
(Some(ptr), flds.clone())
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected tuple but got {:?}", tpl_val),
|
format!("Expected tuple but got {:?}", tpl_val),
|
||||||
tpl_val_pos,
|
tpl_val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected tuple but got {:?}", mod_val),
|
format!("Expected tuple but got {:?}", mod_val),
|
||||||
mod_val_pos,
|
mod_val_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut ops = self.ops.clone();
|
let mut ops = self.ops.clone();
|
||||||
@ -362,17 +366,14 @@ where
|
|||||||
if let &S(ref sym) = e.as_ref() {
|
if let &S(ref sym) = e.as_ref() {
|
||||||
bindings.push(sym.clone());
|
bindings.push(sym.clone());
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("Not an argument name {:?}", e),
|
format!("Not an argument name {:?}", e),
|
||||||
args_pos,
|
args_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error::new(
|
return Err(Error::new(format!("Fault!!! Bad Argument List"), args_pos));
|
||||||
format!("Fault!!! Bad Argument List"),
|
|
||||||
args_pos,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
let mut ops = self.ops.clone();
|
let mut ops = self.ops.clone();
|
||||||
ops.jump(idx)?;
|
ops.jump(idx)?;
|
||||||
@ -422,10 +423,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_fcall(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_fcall(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
let (f, _) = dbg!(self.pop())?;
|
let (f, _) = self.pop()?;
|
||||||
if let &F(ref f) = f.as_ref() {
|
if let &F(ref f) = f.as_ref() {
|
||||||
let (val, _) = Self::fcall_impl(f, &mut self.stack, self.env.clone())?;
|
let (val, _) = Self::fcall_impl(f, &mut self.stack, self.env.clone())?;
|
||||||
self.push(dbg!(val), pos.clone())?;
|
self.push(val, pos.clone())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -441,18 +442,19 @@ where
|
|||||||
self.push(Rc::new(P(Bool(!val))), operand_pos)?;
|
self.push(Rc::new(P(Bool(!val))), operand_pos)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Boolean but got {:?} in expression at {}",
|
"Expected Boolean but got {:?} in expression at {}",
|
||||||
operand, pos
|
operand, pos
|
||||||
),
|
),
|
||||||
operand_pos,
|
operand_pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_equal(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_equal(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, _) = self.pop()?;
|
||||||
|
// FIXME(jwall): We need to enforce our equality rules here.
|
||||||
self.push(Rc::new(P(Bool(left == right))), pos)?;
|
self.push(Rc::new(P(Bool(left == right))), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -468,13 +470,13 @@ where
|
|||||||
self.push(Rc::new(P(Bool(f > ff))), pos.clone())?;
|
self.push(Rc::new(P(Bool(f > ff))), pos.clone())?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected Numeric values of the same type but got {:?} and {:?}",
|
||||||
left, right
|
left, right
|
||||||
),
|
),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -491,13 +493,13 @@ where
|
|||||||
self.push(Rc::new(P(Bool(f < ff))), pos.clone())?;
|
self.push(Rc::new(P(Bool(f < ff))), pos.clone())?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected Numeric values of the same type but got {:?} and {:?}",
|
||||||
left, right
|
left, right
|
||||||
),
|
),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -514,13 +516,13 @@ where
|
|||||||
self.push(Rc::new(P(Bool(f <= ff))), pos)?;
|
self.push(Rc::new(P(Bool(f <= ff))), pos)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected Numeric values of the same type but got {:?} and {:?}",
|
||||||
left, right
|
left, right
|
||||||
),
|
),
|
||||||
pos,
|
pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -537,13 +539,13 @@ where
|
|||||||
self.push(Rc::new(P(Bool(f >= ff))), pos)?;
|
self.push(Rc::new(P(Bool(f >= ff))), pos)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected Numeric values of the same type but got {:?} and {:?}",
|
||||||
left, right
|
left, right
|
||||||
),
|
),
|
||||||
pos,
|
pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -597,7 +599,7 @@ where
|
|||||||
fn op_push_self(&mut self) -> Result<(), Error> {
|
fn op_push_self(&mut self) -> Result<(), Error> {
|
||||||
// We'll need a self stack.
|
// We'll need a self stack.
|
||||||
let (val, pos) = self.pop()?;
|
let (val, pos) = self.pop()?;
|
||||||
self.self_stack.push((dbg!(val.clone()), pos.clone()));
|
self.self_stack.push((val.clone(), pos.clone()));
|
||||||
self.push(val.clone(), pos)?;
|
self.push(val.clone(), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -625,12 +627,15 @@ where
|
|||||||
fn op_field(&mut self) -> Result<(), Error> {
|
fn op_field(&mut self) -> Result<(), Error> {
|
||||||
// Add a Composite field value to a tuple on the stack
|
// Add a Composite field value to a tuple on the stack
|
||||||
// get value from stack
|
// get value from stack
|
||||||
|
//dbg!(&self.stack);
|
||||||
let (val, _) = self.pop()?;
|
let (val, _) = self.pop()?;
|
||||||
// get name from stack.
|
// get name from stack.
|
||||||
let (name_val, _) = self.pop()?;
|
let (name_val, _) = self.pop()?;
|
||||||
let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
|
let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
|
//dbg!(name_val);
|
||||||
|
//dbg!(val);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
// get composite tuple from stack
|
// get composite tuple from stack
|
||||||
@ -649,9 +654,9 @@ where
|
|||||||
|
|
||||||
fn op_element(&mut self) -> Result<(), Error> {
|
fn op_element(&mut self) -> Result<(), Error> {
|
||||||
// get element from stack.
|
// get element from stack.
|
||||||
let (val, _) = dbg!(self.pop()?);
|
let (val, _) = self.pop()?;
|
||||||
// get next value. It should be a Composite list.
|
// get next value. It should be a Composite list.
|
||||||
let (list, pos) = dbg!(self.pop()?);
|
let (list, pos) = self.pop()?;
|
||||||
if let &C(List(ref elems)) = list.as_ref() {
|
if let &C(List(ref elems)) = list.as_ref() {
|
||||||
// add value to list
|
// add value to list
|
||||||
let mut elems = elems.clone();
|
let mut elems = elems.clone();
|
||||||
@ -670,8 +675,8 @@ where
|
|||||||
|
|
||||||
fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
|
fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
|
||||||
// left and then right
|
// left and then right
|
||||||
let (right, right_pos) = dbg!(self.pop()?);
|
let (right, right_pos) = self.pop()?;
|
||||||
let (left, _) = dbg!(self.pop()?);
|
let (left, _) = self.pop()?;
|
||||||
match right.as_ref() {
|
match right.as_ref() {
|
||||||
&P(Int(i)) => {
|
&P(Int(i)) => {
|
||||||
if let &C(List(ref elems)) = left.as_ref() {
|
if let &C(List(ref elems)) = left.as_ref() {
|
||||||
@ -699,17 +704,17 @@ where
|
|||||||
self.push(Rc::new(P(Empty)), pos)?;
|
self.push(Rc::new(P(Empty)), pos)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Invalid selector index: {:?} target: {:?}", right, left),
|
format!("Invalid selector index: {:?} target: {:?}", right, left),
|
||||||
pos,
|
pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_copy(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_copy(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// This value should always be a tuple
|
// This value should always be a tuple
|
||||||
let (override_val, _) = dbg!(self.pop()?);
|
let (override_val, _) = self.pop()?;
|
||||||
// get targett value. It should be a Module or Tuple.
|
// get targett value. It should be a Module or Tuple.
|
||||||
let (tgt, tgt_pos) = dbg!(self.pop()?);
|
let (tgt, tgt_pos) = self.pop()?;
|
||||||
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
|
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
|
||||||
oflds.clone()
|
oflds.clone()
|
||||||
} else {
|
} else {
|
||||||
@ -758,17 +763,16 @@ where
|
|||||||
vm.ops.jump(ptr.clone())?;
|
vm.ops.jump(ptr.clone())?;
|
||||||
vm.run()?;
|
vm.run()?;
|
||||||
let (result_val, result_pos) = vm.pop()?;
|
let (result_val, result_pos) = vm.pop()?;
|
||||||
self.push(dbg!(result_val), result_pos)?;
|
self.push(result_val, result_pos)?;
|
||||||
} else {
|
} else {
|
||||||
dbg!(&vm.symbols);
|
self.push(Rc::new(vm.symbols_to_tuple(false)), pos)?;
|
||||||
self.push(Rc::new(dbg!(vm.symbols_to_tuple(false))), pos)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Expected a Tuple or a Module but got {:?}", tgt),
|
format!("Expected a Tuple or a Module but got {:?}", tgt),
|
||||||
pos,
|
pos,
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -804,16 +808,16 @@ where
|
|||||||
name_pos: &Position,
|
name_pos: &Position,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if self.reserved_words.contains(name.as_str()) {
|
if self.reserved_words.contains(name.as_str()) {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("{} is a reserved word.", name),
|
format!("{} is a reserved word.", name),
|
||||||
name_pos.clone(),
|
name_pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
if self.symbols.is_bound(&name) && strict {
|
if self.symbols.is_bound(&name) && strict {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("Binding {} already exists", name),
|
format!("Binding {} already exists", name),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
self.symbols.add(name, val, pos.clone());
|
self.symbols.add(name, val, pos.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -826,20 +830,14 @@ where
|
|||||||
) -> Result<(Rc<Value>, Position), Error> {
|
) -> Result<(Rc<Value>, Position), Error> {
|
||||||
if name == "self" {
|
if name == "self" {
|
||||||
if let Some((val, pos)) = self.self_stack.last() {
|
if let Some((val, pos)) = self.self_stack.last() {
|
||||||
return Ok((dbg!(val.clone()), pos.clone()));
|
return Ok((val.clone(), pos.clone()));
|
||||||
}
|
}
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(format!("No such binding {}", name), pos.clone()));
|
||||||
format!("No such binding {}", name),
|
|
||||||
pos.clone()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
match self.symbols.get(name) {
|
match self.symbols.get(name) {
|
||||||
Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())),
|
Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())),
|
||||||
None => {
|
None => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(format!("No such binding {}", name), pos.clone()));
|
||||||
format!("No such binding {}", name),
|
|
||||||
pos.clone()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -859,13 +857,10 @@ where
|
|||||||
(P(Int(i)), P(Int(ii))) => Int(i * ii),
|
(P(Int(i)), P(Int(ii))) => Int(i * ii),
|
||||||
(P(Float(f)), P(Float(ff))) => Float(f * ff),
|
(P(Float(f)), P(Float(ff))) => Float(f * ff),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!("Expected {} but got {:?}", left.type_name(), right),
|
||||||
"Expected numeric values of the same type but got {:?} and {:?}",
|
|
||||||
left, right
|
|
||||||
),
|
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -875,13 +870,10 @@ where
|
|||||||
(P(Int(i)), P(Int(ii))) => Int(i / ii),
|
(P(Int(i)), P(Int(ii))) => Int(i / ii),
|
||||||
(P(Float(f)), P(Float(ff))) => Float(f / ff),
|
(P(Float(f)), P(Float(ff))) => Float(f / ff),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!("Expected {} but got {:?}", left.type_name(), right),
|
||||||
"Expected numeric values of the same type but got {:?} and {:?}",
|
|
||||||
left, right
|
|
||||||
),
|
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -891,13 +883,10 @@ where
|
|||||||
(P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
|
(P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
|
||||||
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
|
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!("Expected {} but got {:?}", left.type_name(), right),
|
||||||
"Expected numeric values of the same type but got {:?} and {:?}",
|
|
||||||
left, right
|
|
||||||
),
|
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -907,13 +896,10 @@ where
|
|||||||
(P(Int(i)), Value::P(Int(ii))) => Int(i % ii),
|
(P(Int(i)), Value::P(Int(ii))) => Int(i % ii),
|
||||||
(P(Float(f)), Value::P(Float(ff))) => Float(f % ff),
|
(P(Float(f)), Value::P(Float(ff))) => Float(f % ff),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!("Expected {} but got {:?}", left.type_name(), right),
|
||||||
"Expected numeric values of the same type but got {:?} and {:?}",
|
|
||||||
left, right
|
|
||||||
),
|
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -939,10 +925,10 @@ where
|
|||||||
C(List(new_list))
|
C(List(new_list))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(dbg!(Error::new(
|
return Err(Error::new(
|
||||||
format!("You can not add {:?} and {:?}", left, right),
|
format!("Expected {} but got {:?}", left.type_name(), right),
|
||||||
pos.clone()
|
pos.clone(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -169,9 +169,7 @@ impl Scope {
|
|||||||
| Val::Empty
|
| Val::Empty
|
||||||
| Val::Float(_)
|
| Val::Float(_)
|
||||||
| Val::Int(_)
|
| Val::Int(_)
|
||||||
| Val::Module(_)
|
| Val::Str(_) => {
|
||||||
| Val::Str(_)
|
|
||||||
| Val::Func(_) => {
|
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -21,15 +21,13 @@ use std;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn test_expr_to_val<'a, C: assets::Cache>(
|
fn test_expr_to_val<'a, O, E>(mut cases: Vec<(Expression, Val)>, mut b: FileBuilder<'a, O, E>)
|
||||||
mut cases: Vec<(Expression, Val)>,
|
where
|
||||||
b: FileBuilder<'a, C>,
|
O: std::io::Write,
|
||||||
) {
|
E: std::io::Write,
|
||||||
|
{
|
||||||
for tpl in cases.drain(0..) {
|
for tpl in cases.drain(0..) {
|
||||||
assert_eq!(
|
assert_eq!(b.eval_expr(tpl.0).unwrap(), Rc::new(tpl.1));
|
||||||
b.eval_expr(&tpl.0, &b.scope.spawn_child()).unwrap(),
|
|
||||||
Rc::new(tpl.1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +37,9 @@ fn test_eval_div_expr_fail() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||||
let registry = ConverterRegistry::make_registry();
|
let registry = ConverterRegistry::make_registry();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let out: Vec<u8> = Vec::new();
|
||||||
|
let err: Vec<u8> = Vec::new();
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -64,9 +64,9 @@ fn test_eval_div_expr_fail() {
|
|||||||
#[should_panic(expected = "Expected Float")]
|
#[should_panic(expected = "Expected Float")]
|
||||||
fn test_eval_mul_expr_fail() {
|
fn test_eval_mul_expr_fail() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -91,9 +91,9 @@ fn test_eval_mul_expr_fail() {
|
|||||||
#[should_panic(expected = "Expected Float")]
|
#[should_panic(expected = "Expected Float")]
|
||||||
fn test_eval_subtract_expr_fail() {
|
fn test_eval_subtract_expr_fail() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -117,9 +117,9 @@ fn test_eval_subtract_expr_fail() {
|
|||||||
#[should_panic(expected = "Expected Float")]
|
#[should_panic(expected = "Expected Float")]
|
||||||
fn test_eval_add_expr_fail() {
|
fn test_eval_add_expr_fail() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -140,31 +140,14 @@ fn test_eval_add_expr_fail() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_eval_simple_lookup_error() {
|
|
||||||
let i_paths = Vec::new();
|
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
|
||||||
let registry = ConverterRegistry::make_registry();
|
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
|
||||||
b.scope
|
|
||||||
.build_output
|
|
||||||
.entry(value_node!("var1".to_string(), Position::new(1, 0, 0)))
|
|
||||||
.or_insert(Rc::new(Val::Int(1)));
|
|
||||||
let expr = Expression::Simple(Value::Symbol(value_node!(
|
|
||||||
"var".to_string(),
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
)));
|
|
||||||
assert!(b.eval_expr(&expr, &b.scope.spawn_child()).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include nested for each.
|
// Include nested for each.
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "Unable to find binding tpl1")]
|
#[should_panic(expected = "No such binding tpl1")]
|
||||||
fn test_expr_copy_no_such_tuple() {
|
fn test_expr_copy_no_such_tuple() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Copy(CopyDef {
|
Expression::Copy(CopyDef {
|
||||||
@ -180,46 +163,3 @@ fn test_expr_copy_no_such_tuple() {
|
|||||||
b,
|
b,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "Expected String but got Integer in Select expression")]
|
|
||||||
fn test_select_expr_not_a_string() {
|
|
||||||
let i_paths = Vec::new();
|
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
|
||||||
let registry = ConverterRegistry::make_registry();
|
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
|
||||||
b.scope
|
|
||||||
.build_output
|
|
||||||
.entry(value_node!("foo".to_string(), Position::new(1, 0, 0)))
|
|
||||||
.or_insert(Rc::new(Val::Int(4)));
|
|
||||||
test_expr_to_val(
|
|
||||||
vec![(
|
|
||||||
Expression::Select(SelectDef {
|
|
||||||
val: Box::new(Expression::Simple(Value::Symbol(value_node!(
|
|
||||||
"foo".to_string(),
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
)))),
|
|
||||||
default: Some(Box::new(Expression::Simple(Value::Int(value_node!(
|
|
||||||
1,
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
))))),
|
|
||||||
tuple: vec![
|
|
||||||
(
|
|
||||||
make_tok!("bar", Position::new(1, 1, 1)),
|
|
||||||
Expression::Simple(Value::Int(value_node!(2, Position::new(1, 1, 1)))),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
make_tok!("quux", Position::new(1, 1, 1)),
|
|
||||||
Expression::Simple(Value::Str(value_node!(
|
|
||||||
"2".to_string(),
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
))),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
pos: Position::new(1, 0, 0),
|
|
||||||
}),
|
|
||||||
Val::Int(2),
|
|
||||||
)],
|
|
||||||
b,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -73,18 +73,10 @@ impl EnvConverter {
|
|||||||
&Val::Tuple(ref flds) => {
|
&Val::Tuple(ref flds) => {
|
||||||
self.convert_tuple(flds, w)?;
|
self.convert_tuple(flds, w)?;
|
||||||
}
|
}
|
||||||
&Val::Func(ref _def) => {
|
|
||||||
// This is ignored
|
|
||||||
eprintln!("Skipping func...");
|
|
||||||
}
|
|
||||||
&Val::Env(ref _fs) => {
|
&Val::Env(ref _fs) => {
|
||||||
// This is ignored
|
// This is ignored
|
||||||
eprintln!("Skipping env...");
|
eprintln!("Skipping env...");
|
||||||
}
|
}
|
||||||
&Val::Module(ref _def) => {
|
|
||||||
// This is ignored
|
|
||||||
eprintln!("Skipping module...");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -194,21 +194,18 @@ impl Converter for ExecConverter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod exec_test {
|
mod exec_test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::build::assets::MemoryCache;
|
|
||||||
use crate::build::FileBuilder;
|
use crate::build::FileBuilder;
|
||||||
use crate::convert::traits::Converter;
|
use crate::convert::traits::Converter;
|
||||||
use crate::convert::ConverterRegistry;
|
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_just_command_test() {
|
fn convert_just_command_test() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
@ -229,9 +226,9 @@ mod exec_test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn convert_command_with_env_test() {
|
fn convert_command_with_env_test() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
@ -259,9 +256,9 @@ mod exec_test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn convert_command_with_arg_test() {
|
fn convert_command_with_arg_test() {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let out: Vec<u8> = Vec::new();
|
||||||
let registry = ConverterRegistry::make_registry();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache, ®istry);
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
|
@ -55,7 +55,7 @@ impl FlagConverter {
|
|||||||
// first of all we need to make sure that each &Val is only a primitive type.
|
// first of all we need to make sure that each &Val is only a primitive type.
|
||||||
for v in def.iter() {
|
for v in def.iter() {
|
||||||
let vref = v.as_ref();
|
let vref = v.as_ref();
|
||||||
if vref.is_list() || vref.is_tuple() || vref.is_func() || vref.is_module() {
|
if vref.is_list() || vref.is_tuple() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Skipping non primitive val in list for flag {}{}",
|
"Skipping non primitive val in list for flag {}{}",
|
||||||
pfx, name
|
pfx, name
|
||||||
@ -86,7 +86,7 @@ impl FlagConverter {
|
|||||||
&Val::Str(ref s) => {
|
&Val::Str(ref s) => {
|
||||||
write!(w, "'{}' ", s)?;
|
write!(w, "'{}' ", s)?;
|
||||||
}
|
}
|
||||||
&Val::List(_) | &Val::Tuple(_) | &Val::Func(_) | &Val::Env(_) | &Val::Module(_) => {
|
&Val::List(_) | &Val::Tuple(_) | &Val::Env(_) => {
|
||||||
// This is ignored
|
// This is ignored
|
||||||
eprintln!("Skipping {}...", v.type_name());
|
eprintln!("Skipping {}...", v.type_name());
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ impl FlagConverter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match val.as_ref() {
|
match val.as_ref() {
|
||||||
&Val::Tuple(_) | &Val::Module(_) | &Val::Func(_) | &Val::Env(_) => {
|
&Val::Tuple(_) | &Val::Env(_) => {
|
||||||
eprintln!("Skipping {} in flag output tuple.", val.type_name());
|
eprintln!("Skipping {} in flag output tuple.", val.type_name());
|
||||||
}
|
}
|
||||||
&Val::List(ref def) => {
|
&Val::List(ref def) => {
|
||||||
|
@ -72,14 +72,6 @@ impl JsonConverter {
|
|||||||
serde_json::Value::Number(n)
|
serde_json::Value::Number(n)
|
||||||
}
|
}
|
||||||
&Val::Str(ref s) => serde_json::Value::String(s.clone()),
|
&Val::Str(ref s) => serde_json::Value::String(s.clone()),
|
||||||
&Val::Func(_) => {
|
|
||||||
eprintln!("Skipping func encoding as null...");
|
|
||||||
serde_json::Value::Null
|
|
||||||
}
|
|
||||||
&Val::Module(_) => {
|
|
||||||
eprintln!("Skipping module encoding as null...");
|
|
||||||
serde_json::Value::Null
|
|
||||||
}
|
|
||||||
&Val::Env(ref fs) => self.convert_env(fs)?,
|
&Val::Env(ref fs) => self.convert_env(fs)?,
|
||||||
&Val::List(ref l) => self.convert_list(l)?,
|
&Val::List(ref l) => self.convert_list(l)?,
|
||||||
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
||||||
|
@ -68,14 +68,6 @@ impl TomlConverter {
|
|||||||
&Val::Float(f) => toml::Value::Float(f),
|
&Val::Float(f) => toml::Value::Float(f),
|
||||||
&Val::Int(i) => toml::Value::Integer(i),
|
&Val::Int(i) => toml::Value::Integer(i),
|
||||||
&Val::Str(ref s) => toml::Value::String(s.clone()),
|
&Val::Str(ref s) => toml::Value::String(s.clone()),
|
||||||
&Val::Func(_) => {
|
|
||||||
let err = SimpleError::new("Functions are not allowed in Toml Conversions!");
|
|
||||||
return Err(Box::new(err));
|
|
||||||
}
|
|
||||||
&Val::Module(_) => {
|
|
||||||
let err = SimpleError::new("Modules are not allowed in Toml Conversions!");
|
|
||||||
return Err(Box::new(err));
|
|
||||||
}
|
|
||||||
&Val::Env(ref fs) => self.convert_env(fs)?,
|
&Val::Env(ref fs) => self.convert_env(fs)?,
|
||||||
&Val::List(ref l) => self.convert_list(l)?,
|
&Val::List(ref l) => self.convert_list(l)?,
|
||||||
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
||||||
|
@ -57,14 +57,6 @@ impl YamlConverter {
|
|||||||
_ => panic!("Int is too large or not a Number {}", i),
|
_ => panic!("Int is too large or not a Number {}", i),
|
||||||
},
|
},
|
||||||
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
|
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
|
||||||
&Val::Func(_) => {
|
|
||||||
eprintln!("Skipping func encoding as null...");
|
|
||||||
serde_yaml::Value::Null
|
|
||||||
}
|
|
||||||
&Val::Module(_) => {
|
|
||||||
eprintln!("Skipping module encoding as null...");
|
|
||||||
serde_yaml::Value::Null
|
|
||||||
}
|
|
||||||
&Val::Env(ref fs) => self.convert_env(fs)?,
|
&Val::Env(ref fs) => self.convert_env(fs)?,
|
||||||
&Val::List(ref l) => self.convert_list(l)?,
|
&Val::List(ref l) => self.convert_list(l)?,
|
||||||
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user