mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 18:21:38 +03:00
format string and grammar changes
This commit is contained in:
parent
9facd3e984
commit
a9593971b9
@ -92,7 +92,7 @@ impl<'a> MonoidalReducerStatement<'a, BoolAnd> for ReturnPathReducer {
|
|||||||
if_true.append(if_false.unwrap_or(BoolAnd(false)))
|
if_true.append(if_false.unwrap_or(BoolAnd(false)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_formatted_string(&mut self, input: &FormatString, parameters: Vec<BoolAnd>) -> BoolAnd {
|
fn reduce_formatted_string(&mut self, input: &ConsoleArgs, parameters: Vec<BoolAnd>) -> BoolAnd {
|
||||||
BoolAnd(false)
|
BoolAnd(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +109,29 @@ pub enum CharValue {
|
|||||||
NonScalar(u32),
|
NonScalar(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&leo_ast::Char> for CharValue {
|
||||||
|
fn from(other: &leo_ast::Char) -> Self {
|
||||||
|
use leo_ast::Char::*;
|
||||||
|
match other {
|
||||||
|
Scalar(value) => CharValue::Scalar(*value),
|
||||||
|
NonScalar(value) => CharValue::NonScalar(*value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<leo_ast::Char> for &CharValue {
|
||||||
|
fn into(self) -> leo_ast::Char {
|
||||||
|
use leo_ast::Char::*;
|
||||||
|
match self {
|
||||||
|
CharValue::Scalar(value) => Scalar(*value),
|
||||||
|
CharValue::NonScalar(value) => NonScalar(*value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<leo_ast::CharValue> for CharValue {
|
impl From<leo_ast::CharValue> for CharValue {
|
||||||
fn from(other: leo_ast::CharValue) -> Self {
|
fn from(other: leo_ast::CharValue) -> Self {
|
||||||
use leo_ast::Char::*;
|
Self::from(&other.character)
|
||||||
match other.character {
|
|
||||||
Scalar(value) => CharValue::Scalar(value),
|
|
||||||
NonScalar(value) => CharValue::NonScalar(value),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ impl<'a, T: Monoid, R: MonoidalReducerStatement<'a, T>> MonoidalDirector<'a, T,
|
|||||||
.reduce_conditional_statement(input, condition, if_true, if_false)
|
.reduce_conditional_statement(input, condition, if_true, if_false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce_formatted_string(&mut self, input: &FormatString<'a>) -> T {
|
pub fn reduce_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> T {
|
||||||
let parameters = input
|
let parameters = input
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -118,7 +118,7 @@ pub trait MonoidalReducerStatement<'a, T: Monoid>: MonoidalReducerExpression<'a,
|
|||||||
condition.append(if_true).append_option(if_false)
|
condition.append(if_true).append_option(if_false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_formatted_string(&mut self, input: &FormatString<'a>, parameters: Vec<T>) -> T {
|
fn reduce_formatted_string(&mut self, input: &ConsoleArgs<'a>, parameters: Vec<T>) -> T {
|
||||||
T::default().append_all(parameters.into_iter())
|
T::default().append_all(parameters.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ impl<'a, R: ReconstructingReducerStatement<'a>> ReconstructingDirector<'a, R> {
|
|||||||
.reduce_conditional_statement(input, condition, if_true, if_false)
|
.reduce_conditional_statement(input, condition, if_true, if_false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce_formatted_string(&mut self, input: FormatString<'a>) -> FormatString<'a> {
|
pub fn reduce_formatted_string(&mut self, input: ConsoleArgs<'a>) -> ConsoleArgs<'a> {
|
||||||
let parameters = input
|
let parameters = input
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -274,12 +274,12 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a
|
|||||||
|
|
||||||
fn reduce_formatted_string(
|
fn reduce_formatted_string(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: FormatString<'a>,
|
input: ConsoleArgs<'a>,
|
||||||
parameters: Vec<&'a Expression<'a>>,
|
parameters: Vec<&'a Expression<'a>>,
|
||||||
) -> FormatString<'a> {
|
) -> ConsoleArgs<'a> {
|
||||||
FormatString {
|
ConsoleArgs {
|
||||||
span: input.span,
|
span: input.span,
|
||||||
parts: input.parts,
|
string: input.string,
|
||||||
parameters: parameters.into_iter().map(Cell::new).collect(),
|
parameters: parameters.into_iter().map(Cell::new).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_console_log(&mut self, input: ConsoleStatement<'a>, argument: FormatString<'a>) -> Statement<'a> {
|
fn reduce_console_log(&mut self, input: ConsoleStatement<'a>, argument: ConsoleArgs<'a>) -> Statement<'a> {
|
||||||
assert!(!matches!(input.function, ConsoleFunction::Assert(_)));
|
assert!(!matches!(input.function, ConsoleFunction::Assert(_)));
|
||||||
Statement::Console(ConsoleStatement {
|
Statement::Console(ConsoleStatement {
|
||||||
parent: input.parent,
|
parent: input.parent,
|
||||||
|
@ -120,7 +120,7 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_formatted_string(&mut self, input: &FormatString<'a>) -> VisitResult {
|
fn visit_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> VisitResult {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ impl<'a, R: StatementVisitor<'a>> VisitorDirector<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visit_formatted_string(&mut self, input: &FormatString<'a>) -> ConcreteVisitResult {
|
pub fn visit_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> ConcreteVisitResult {
|
||||||
match self.visitor.visit_formatted_string(input) {
|
match self.visitor.visit_formatted_string(input) {
|
||||||
VisitResult::VisitChildren => {
|
VisitResult::VisitChildren => {
|
||||||
for parameter in input.parameters.iter() {
|
for parameter in input.parameters.iter() {
|
||||||
|
@ -14,15 +14,15 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
|
use crate::{AsgConvertError, CharValue, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
|
||||||
use leo_ast::{ConsoleFunction as AstConsoleFunction, FormatStringPart};
|
use leo_ast::ConsoleFunction as AstConsoleFunction;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
// TODO (protryon): Refactor to not require/depend on span
|
// TODO (protryon): Refactor to not require/depend on span
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FormatString<'a> {
|
pub struct ConsoleArgs<'a> {
|
||||||
pub parts: Vec<FormatStringPart>,
|
pub string: Vec<CharValue>,
|
||||||
pub parameters: Vec<Cell<&'a Expression<'a>>>,
|
pub parameters: Vec<Cell<&'a Expression<'a>>>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
@ -30,9 +30,9 @@ pub struct FormatString<'a> {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ConsoleFunction<'a> {
|
pub enum ConsoleFunction<'a> {
|
||||||
Assert(Cell<&'a Expression<'a>>),
|
Assert(Cell<&'a Expression<'a>>),
|
||||||
Debug(FormatString<'a>),
|
Debug(ConsoleArgs<'a>),
|
||||||
Error(FormatString<'a>),
|
Error(ConsoleArgs<'a>),
|
||||||
Log(FormatString<'a>),
|
Log(ConsoleArgs<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -48,41 +48,42 @@ impl<'a> Node for ConsoleStatement<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromAst<'a, leo_ast::FormatString> for FormatString<'a> {
|
impl<'a> FromAst<'a, leo_ast::ConsoleArgs> for ConsoleArgs<'a> {
|
||||||
fn from_ast(
|
fn from_ast(
|
||||||
scope: &'a Scope<'a>,
|
scope: &'a Scope<'a>,
|
||||||
value: &leo_ast::FormatString,
|
value: &leo_ast::ConsoleArgs,
|
||||||
_expected_type: Option<PartialType<'a>>,
|
_expected_type: Option<PartialType<'a>>,
|
||||||
) -> Result<Self, AsgConvertError> {
|
) -> Result<Self, AsgConvertError> {
|
||||||
let expected_param_len = value
|
// let expected_param_len = value
|
||||||
.parts
|
// .parts
|
||||||
.iter()
|
// .iter()
|
||||||
.filter(|x| matches!(x, FormatStringPart::Container))
|
// .filter(|x| matches!(x, FormatStringPart::Container))
|
||||||
.count();
|
// .count();
|
||||||
if value.parameters.len() != expected_param_len {
|
// if value.parameters.len() != expected_param_len {
|
||||||
// + 1 for formatting string as to not confuse user
|
// + 1 for formatting string as to not confuse user
|
||||||
return Err(AsgConvertError::unexpected_call_argument_count(
|
// return Err(AsgConvertError::unexpected_call_argument_count(
|
||||||
expected_param_len + 1,
|
// expected_param_len + 1,
|
||||||
value.parameters.len() + 1,
|
// value.parameters.len() + 1,
|
||||||
&value.span,
|
// &value.span,
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
let mut parameters = vec![];
|
let mut parameters = vec![];
|
||||||
for parameter in value.parameters.iter() {
|
for parameter in value.parameters.iter() {
|
||||||
parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
|
parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
|
||||||
}
|
}
|
||||||
Ok(FormatString {
|
Ok(ConsoleArgs {
|
||||||
parts: value.parts.clone(),
|
string: value.string.iter().map(CharValue::from).collect::<Vec<_>>(),
|
||||||
parameters,
|
parameters,
|
||||||
span: value.span.clone(),
|
span: value.span.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Into<leo_ast::FormatString> for &FormatString<'a> {
|
impl<'a> Into<leo_ast::ConsoleArgs> for &ConsoleArgs<'a> {
|
||||||
fn into(self) -> leo_ast::FormatString {
|
fn into(self) -> leo_ast::ConsoleArgs {
|
||||||
leo_ast::FormatString {
|
leo_ast::ConsoleArgs {
|
||||||
parts: self.parts.clone(),
|
string: self.string.iter().map(|c| c.into()).collect::<Vec<_>>(),
|
||||||
parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
|
parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
|
||||||
span: self.span.clone(),
|
span: self.span.clone(),
|
||||||
}
|
}
|
||||||
@ -102,15 +103,9 @@ impl<'a> FromAst<'a, leo_ast::ConsoleStatement> for ConsoleStatement<'a> {
|
|||||||
AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Cell::new(
|
AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Cell::new(
|
||||||
<&Expression<'a>>::from_ast(scope, expression, Some(Type::Boolean.into()))?,
|
<&Expression<'a>>::from_ast(scope, expression, Some(Type::Boolean.into()))?,
|
||||||
)),
|
)),
|
||||||
AstConsoleFunction::Debug(formatted_string) => {
|
AstConsoleFunction::Debug(args) => ConsoleFunction::Debug(ConsoleArgs::from_ast(scope, args, None)?),
|
||||||
ConsoleFunction::Debug(FormatString::from_ast(scope, formatted_string, None)?)
|
AstConsoleFunction::Error(args) => ConsoleFunction::Error(ConsoleArgs::from_ast(scope, args, None)?),
|
||||||
}
|
AstConsoleFunction::Log(args) => ConsoleFunction::Log(ConsoleArgs::from_ast(scope, args, None)?),
|
||||||
AstConsoleFunction::Error(formatted_string) => {
|
|
||||||
ConsoleFunction::Error(FormatString::from_ast(scope, formatted_string, None)?)
|
|
||||||
}
|
|
||||||
AstConsoleFunction::Log(formatted_string) => {
|
|
||||||
ConsoleFunction::Log(FormatString::from_ast(scope, formatted_string, None)?)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -122,9 +117,9 @@ impl<'a> Into<leo_ast::ConsoleStatement> for &ConsoleStatement<'a> {
|
|||||||
leo_ast::ConsoleStatement {
|
leo_ast::ConsoleStatement {
|
||||||
function: match &self.function {
|
function: match &self.function {
|
||||||
Assert(e) => AstConsoleFunction::Assert(e.get().into()),
|
Assert(e) => AstConsoleFunction::Assert(e.get().into()),
|
||||||
Debug(formatted_string) => AstConsoleFunction::Debug(formatted_string.into()),
|
Debug(args) => AstConsoleFunction::Debug(args.into()),
|
||||||
Error(formatted_string) => AstConsoleFunction::Error(formatted_string.into()),
|
Error(args) => AstConsoleFunction::Error(args.into()),
|
||||||
Log(formatted_string) => AstConsoleFunction::Log(formatted_string.into()),
|
Log(args) => AstConsoleFunction::Log(args.into()),
|
||||||
},
|
},
|
||||||
span: self.span.clone().unwrap_or_default(),
|
span: self.span.clone().unwrap_or_default(),
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
function main() {
|
|
||||||
console.log("{}");
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
function main() {
|
|
||||||
console.log("", 1u32);
|
|
||||||
}
|
|
@ -27,15 +27,3 @@ fn test_log_parameter_fail_unknown() {
|
|||||||
let program_string = include_str!("log_parameter_fail_unknown.leo");
|
let program_string = include_str!("log_parameter_fail_unknown.leo");
|
||||||
load_asg(program_string).err().unwrap();
|
load_asg(program_string).err().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log_parameter_fail_empty() {
|
|
||||||
let program_string = include_str!("log_parameter_fail_empty.leo");
|
|
||||||
load_asg(program_string).err().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log_parameter_fail_none() {
|
|
||||||
let program_string = include_str!("log_parameter_fail_empty.leo");
|
|
||||||
load_asg(program_string).err().unwrap();
|
|
||||||
}
|
|
||||||
|
@ -35,6 +35,13 @@ impl ReducerError {
|
|||||||
ReducerError::Error(FormattedError::new_from_span(message, span))
|
ReducerError::Error(FormattedError::new_from_span(message, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty_string(span: &Span) -> Self {
|
||||||
|
let message =
|
||||||
|
"Cannot constrcut an empty string: it has the type of [char; 0] which is not possible.".to_string();
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn impossible_console_assert_call(span: &Span) -> Self {
|
pub fn impossible_console_assert_call(span: &Span) -> Self {
|
||||||
let message = "Console::Assert cannot be matched here, its handled in another case.".to_string();
|
let message = "Console::Assert cannot be matched here, its handled in another case.".to_string();
|
||||||
|
|
||||||
|
@ -391,23 +391,23 @@ impl Canonicalizer {
|
|||||||
ConsoleFunction::Assert(expression) => {
|
ConsoleFunction::Assert(expression) => {
|
||||||
ConsoleFunction::Assert(self.canonicalize_expression(expression))
|
ConsoleFunction::Assert(self.canonicalize_expression(expression))
|
||||||
}
|
}
|
||||||
ConsoleFunction::Debug(format) | ConsoleFunction::Error(format) | ConsoleFunction::Log(format) => {
|
ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => {
|
||||||
let parameters = format
|
let parameters = args
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.map(|parameter| self.canonicalize_expression(parameter))
|
.map(|parameter| self.canonicalize_expression(parameter))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let formatted = FormatString {
|
let console_args = ConsoleArgs {
|
||||||
parts: format.parts.clone(),
|
string: args.string.clone(),
|
||||||
parameters,
|
parameters,
|
||||||
span: format.span.clone(),
|
span: args.span.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match &console_function_call.function {
|
match &console_function_call.function {
|
||||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(console_args),
|
||||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args),
|
||||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args),
|
||||||
_ => unimplemented!(), // impossible
|
_ => unimplemented!(), // impossible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,6 +493,10 @@ impl ReconstructingReducer for Canonicalizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_string(&mut self, string: &[Char], span: &Span) -> Result<Expression, ReducerError> {
|
fn reduce_string(&mut self, string: &[Char], span: &Span) -> Result<Expression, ReducerError> {
|
||||||
|
if string.is_empty() {
|
||||||
|
return Err(ReducerError::empty_string(span));
|
||||||
|
}
|
||||||
|
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
let mut col_adder = 0;
|
let mut col_adder = 0;
|
||||||
for (index, character) in string.iter().enumerate() {
|
for (index, character) in string.iter().enumerate() {
|
||||||
|
@ -390,23 +390,23 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
|||||||
) -> Result<ConsoleStatement, ReducerError> {
|
) -> Result<ConsoleStatement, ReducerError> {
|
||||||
let function = match &console_function_call.function {
|
let function = match &console_function_call.function {
|
||||||
ConsoleFunction::Assert(expression) => ConsoleFunction::Assert(self.reduce_expression(expression)?),
|
ConsoleFunction::Assert(expression) => ConsoleFunction::Assert(self.reduce_expression(expression)?),
|
||||||
ConsoleFunction::Debug(format) | ConsoleFunction::Error(format) | ConsoleFunction::Log(format) => {
|
ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => {
|
||||||
let mut parameters = vec![];
|
let mut parameters = vec![];
|
||||||
for parameter in format.parameters.iter() {
|
for parameter in args.parameters.iter() {
|
||||||
parameters.push(self.reduce_expression(parameter)?);
|
parameters.push(self.reduce_expression(parameter)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let formatted = FormatString {
|
let formatted = ConsoleArgs {
|
||||||
parts: format.parts.clone(),
|
string: args.string.clone(),
|
||||||
parameters,
|
parameters,
|
||||||
span: format.span.clone(),
|
span: args.span.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match &console_function_call.function {
|
match &console_function_call.function {
|
||||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
||||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
||||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
||||||
_ => return Err(ReducerError::impossible_console_assert_call(&format.span)),
|
_ => return Err(ReducerError::impossible_console_assert_call(&args.span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
96
ast/src/statements/console/console_args.rs
Normal file
96
ast/src/statements/console/console_args.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::{Char, Expression, Node, Span};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
// use tendril::StrTendril;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
|
// pub enum FormatStringPart {
|
||||||
|
// Const(#[serde(with = "crate::common::tendril_json")] StrTendril),
|
||||||
|
// Container,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl FormatStringPart {
|
||||||
|
// pub fn from_string(string: Vec<Char>) -> Vec<Self> {
|
||||||
|
// let mut parts = Vec::new();
|
||||||
|
// let mut in_container = false;
|
||||||
|
// let mut substring = String::new();
|
||||||
|
// for (_, character) in string.iter().enumerate() {
|
||||||
|
// match character {
|
||||||
|
// Char::Scalar(scalar) => match scalar {
|
||||||
|
// '{' if !in_container => {
|
||||||
|
// parts.push(FormatStringPart::Const(substring.clone().into()));
|
||||||
|
// substring.clear();
|
||||||
|
// in_container = true;
|
||||||
|
// }
|
||||||
|
// '}' if in_container => {
|
||||||
|
// in_container = false;
|
||||||
|
// parts.push(FormatStringPart::Container);
|
||||||
|
// }
|
||||||
|
// _ if in_container => {
|
||||||
|
// in_container = false;
|
||||||
|
// }
|
||||||
|
// _ => substring.push(*scalar),
|
||||||
|
// },
|
||||||
|
// Char::NonScalar(non_scalar) => {
|
||||||
|
// substring.push_str(format!("\\u{{{:x}}}", non_scalar).as_str());
|
||||||
|
// in_container = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if !substring.is_empty() {
|
||||||
|
// parts.push(FormatStringPart::Const(substring.into()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// parts
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
|
pub struct ConsoleArgs {
|
||||||
|
pub string: Vec<Char>,
|
||||||
|
pub parameters: Vec<Expression>,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ConsoleArgs {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"\"{}\", {}",
|
||||||
|
self.string.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(""),
|
||||||
|
self.parameters
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for ConsoleArgs {
|
||||||
|
fn span(&self) -> &Span {
|
||||||
|
&self.span
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_span(&mut self, span: Span) {
|
||||||
|
self.span = span;
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Expression, FormatString, Node, Span};
|
use crate::{ConsoleArgs, Expression, Node, Span};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -22,9 +22,9 @@ use std::fmt;
|
|||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub enum ConsoleFunction {
|
pub enum ConsoleFunction {
|
||||||
Assert(Expression),
|
Assert(Expression),
|
||||||
Debug(FormatString),
|
Debug(ConsoleArgs),
|
||||||
Error(FormatString),
|
Error(ConsoleArgs),
|
||||||
Log(FormatString),
|
Log(ConsoleArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ConsoleFunction {
|
impl fmt::Display for ConsoleFunction {
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
|
||||||
// This file is part of the Leo library.
|
|
||||||
|
|
||||||
// The Leo library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// The Leo library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
use crate::{Char, Expression, Node, Span};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::fmt;
|
|
||||||
use tendril::StrTendril;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
|
||||||
pub enum FormatStringPart {
|
|
||||||
Const(#[serde(with = "crate::common::tendril_json")] StrTendril),
|
|
||||||
Container,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FormatStringPart {
|
|
||||||
pub fn from_string(string: Vec<Char>) -> Vec<Self> {
|
|
||||||
let mut parts = Vec::new();
|
|
||||||
let mut in_container = false;
|
|
||||||
let mut substring = String::new();
|
|
||||||
for (_, character) in string.iter().enumerate() {
|
|
||||||
match character {
|
|
||||||
Char::Scalar(scalar) => match scalar {
|
|
||||||
'{' if !in_container => {
|
|
||||||
parts.push(FormatStringPart::Const(substring.clone().into()));
|
|
||||||
substring.clear();
|
|
||||||
in_container = true;
|
|
||||||
}
|
|
||||||
'}' if in_container => {
|
|
||||||
in_container = false;
|
|
||||||
parts.push(FormatStringPart::Container);
|
|
||||||
}
|
|
||||||
_ if in_container => {
|
|
||||||
in_container = false;
|
|
||||||
}
|
|
||||||
_ => substring.push(*scalar),
|
|
||||||
},
|
|
||||||
Char::NonScalar(non_scalar) => {
|
|
||||||
substring.push_str(format!("\\u{{{:x}}}", non_scalar).as_str());
|
|
||||||
in_container = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !substring.is_empty() {
|
|
||||||
parts.push(FormatStringPart::Const(substring.into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
parts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
|
||||||
pub struct FormatString {
|
|
||||||
pub parts: Vec<FormatStringPart>,
|
|
||||||
pub parameters: Vec<Expression>,
|
|
||||||
pub span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for FormatString {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"\"{}\", {}",
|
|
||||||
self.parts
|
|
||||||
.iter()
|
|
||||||
.map(|x| match x {
|
|
||||||
FormatStringPart::Const(x) => x.to_string(),
|
|
||||||
FormatStringPart::Container => "{}".to_string(),
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(""),
|
|
||||||
self.parameters
|
|
||||||
.iter()
|
|
||||||
.map(|p| p.to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(",")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Node for FormatString {
|
|
||||||
fn span(&self) -> &Span {
|
|
||||||
&self.span
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_span(&mut self, span: Span) {
|
|
||||||
self.span = span;
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,11 +17,8 @@
|
|||||||
pub mod console_function;
|
pub mod console_function;
|
||||||
pub use console_function::*;
|
pub use console_function::*;
|
||||||
|
|
||||||
|
pub mod console_args;
|
||||||
|
pub use console_args::*;
|
||||||
|
|
||||||
pub mod console_statement;
|
pub mod console_statement;
|
||||||
pub use console_statement::*;
|
pub use console_statement::*;
|
||||||
|
|
||||||
pub mod formatted_container;
|
|
||||||
pub use formatted_container::*;
|
|
||||||
|
|
||||||
pub mod formatted_string;
|
|
||||||
pub use formatted_string::*;
|
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
//! Evaluates a formatted string in a compiled Leo program.
|
//! Evaluates a formatted string in a compiled Leo program.
|
||||||
|
|
||||||
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
|
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
|
||||||
use leo_asg::FormatString;
|
use leo_asg::{CharValue, ConsoleArgs};
|
||||||
use leo_ast::FormatStringPart;
|
|
||||||
use snarkvm_fields::PrimeField;
|
use snarkvm_fields::PrimeField;
|
||||||
use snarkvm_r1cs::ConstraintSystem;
|
use snarkvm_r1cs::ConstraintSystem;
|
||||||
|
|
||||||
@ -26,35 +25,65 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
pub fn format<CS: ConstraintSystem<F>>(
|
pub fn format<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
formatted: &FormatString<'a>,
|
args: &ConsoleArgs<'a>,
|
||||||
) -> Result<String, ConsoleError> {
|
) -> Result<String, ConsoleError> {
|
||||||
// Check that containers and parameters match
|
let mut out = Vec::new();
|
||||||
let container_count = formatted
|
let mut in_container = false;
|
||||||
.parts
|
let mut substring = String::new();
|
||||||
.iter()
|
let mut arg_index = 0;
|
||||||
.filter(|x| matches!(x, FormatStringPart::Container))
|
let mut escape_right_bracket = false;
|
||||||
.count();
|
for (index, character) in args.string.iter().enumerate() {
|
||||||
if container_count != formatted.parameters.len() {
|
match character {
|
||||||
return Err(ConsoleError::length(
|
_ if escape_right_bracket => {
|
||||||
container_count,
|
escape_right_bracket = false;
|
||||||
formatted.parameters.len(),
|
continue;
|
||||||
&formatted.span,
|
}
|
||||||
));
|
CharValue::Scalar(scalar) => match scalar {
|
||||||
}
|
'{' if !in_container => {
|
||||||
|
out.push(substring.clone());
|
||||||
let mut executed_containers = Vec::with_capacity(formatted.parameters.len());
|
substring.clear();
|
||||||
for parameter in formatted.parameters.iter() {
|
in_container = true;
|
||||||
executed_containers.push(self.enforce_expression(cs, parameter.get())?.to_string());
|
}
|
||||||
}
|
'{' if in_container => {
|
||||||
|
substring.push('{');
|
||||||
let mut out = vec![];
|
in_container = false;
|
||||||
let mut parameters = executed_containers.iter();
|
}
|
||||||
for part in formatted.parts.iter() {
|
'}' if in_container => {
|
||||||
match part {
|
in_container = false;
|
||||||
FormatStringPart::Const(c) => out.push(c.to_string()),
|
let parameter = match args.parameters.get(arg_index) {
|
||||||
FormatStringPart::Container => out.push(parameters.next().unwrap().to_string()),
|
Some(index) => index,
|
||||||
|
None => return Err(ConsoleError::length(arg_index + 1, args.parameters.len(), &args.span)),
|
||||||
|
};
|
||||||
|
out.push(self.enforce_expression(cs, parameter.get())?.to_string());
|
||||||
|
arg_index += 1;
|
||||||
|
}
|
||||||
|
'}' if !in_container => {
|
||||||
|
if let Some(CharValue::Scalar(next)) = args.string.get(index + 1) {
|
||||||
|
if *next == '}' {
|
||||||
|
substring.push('}');
|
||||||
|
escape_right_bracket = true;
|
||||||
|
} else {
|
||||||
|
return Err(ConsoleError::expected_escaped_right_brace(&args.span));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ if in_container => {
|
||||||
|
return Err(ConsoleError::expected_left_or_right_brace(&args.span));
|
||||||
|
}
|
||||||
|
_ => substring.push(*scalar),
|
||||||
|
},
|
||||||
|
CharValue::NonScalar(non_scalar) => {
|
||||||
|
substring.push_str(format!("\\u{{{:x}}}", non_scalar).as_str());
|
||||||
|
in_container = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out.push(substring);
|
||||||
|
|
||||||
|
// Check that containers and parameters match
|
||||||
|
if arg_index != args.parameters.len() {
|
||||||
|
return Err(ConsoleError::length(arg_index, args.parameters.len(), &args.span));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(out.join(""))
|
Ok(out.join(""))
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,18 @@ impl ConsoleError {
|
|||||||
ConsoleError::Error(FormattedError::new_from_span(message, span))
|
ConsoleError::Error(FormattedError::new_from_span(message, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expected_left_or_right_brace(span: &Span) -> Self {
|
||||||
|
let message = "Formatter given a {. Expected a { or } after".to_string();
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expected_escaped_right_brace(span: &Span) -> Self {
|
||||||
|
let message = "Formatter given a }. Expected a container {} or }}".to_string();
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn length(containers: usize, parameters: usize, span: &Span) -> Self {
|
pub fn length(containers: usize, parameters: usize, span: &Span) -> Self {
|
||||||
let message = format!(
|
let message = format!(
|
||||||
"Formatter given {} containers and found {} parameters",
|
"Formatter given {} containers and found {} parameters",
|
||||||
|
@ -76,12 +76,12 @@ use leo_ast::{
|
|||||||
CircuitStaticFunctionAccessExpression,
|
CircuitStaticFunctionAccessExpression,
|
||||||
CombinerError,
|
CombinerError,
|
||||||
ConditionalStatement as AstConditionalStatement,
|
ConditionalStatement as AstConditionalStatement,
|
||||||
|
ConsoleArgs as AstConsoleArgs,
|
||||||
ConsoleFunction as AstConsoleFunction,
|
ConsoleFunction as AstConsoleFunction,
|
||||||
ConsoleStatement as AstConsoleStatement,
|
ConsoleStatement as AstConsoleStatement,
|
||||||
DefinitionStatement as AstDefinitionStatement,
|
DefinitionStatement as AstDefinitionStatement,
|
||||||
Expression as AstExpression,
|
Expression as AstExpression,
|
||||||
ExpressionStatement as AstExpressionStatement,
|
ExpressionStatement as AstExpressionStatement,
|
||||||
FormatString,
|
|
||||||
Function as AstFunction,
|
Function as AstFunction,
|
||||||
GroupTuple,
|
GroupTuple,
|
||||||
GroupValue as AstGroupValue,
|
GroupValue as AstGroupValue,
|
||||||
@ -597,25 +597,27 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
|
|||||||
(AstConsoleFunction::Assert(ast_expression), AsgConsoleFunction::Assert(asg_expression)) => {
|
(AstConsoleFunction::Assert(ast_expression), AsgConsoleFunction::Assert(asg_expression)) => {
|
||||||
AstConsoleFunction::Assert(self.reduce_expression(&ast_expression, asg_expression.get())?)
|
AstConsoleFunction::Assert(self.reduce_expression(&ast_expression, asg_expression.get())?)
|
||||||
}
|
}
|
||||||
(AstConsoleFunction::Debug(ast_format), AsgConsoleFunction::Debug(asg_format))
|
(AstConsoleFunction::Debug(ast_console_args), AsgConsoleFunction::Debug(asg_format))
|
||||||
| (AstConsoleFunction::Error(ast_format), AsgConsoleFunction::Error(asg_format))
|
| (AstConsoleFunction::Error(ast_console_args), AsgConsoleFunction::Error(asg_format))
|
||||||
| (AstConsoleFunction::Log(ast_format), AsgConsoleFunction::Log(asg_format)) => {
|
| (AstConsoleFunction::Log(ast_console_args), AsgConsoleFunction::Log(asg_format)) => {
|
||||||
let mut parameters = vec![];
|
let mut parameters = vec![];
|
||||||
for (ast_parameter, asg_parameter) in ast_format.parameters.iter().zip(asg_format.parameters.iter()) {
|
for (ast_parameter, asg_parameter) in
|
||||||
|
ast_console_args.parameters.iter().zip(asg_format.parameters.iter())
|
||||||
|
{
|
||||||
parameters.push(self.reduce_expression(&ast_parameter, asg_parameter.get())?);
|
parameters.push(self.reduce_expression(&ast_parameter, asg_parameter.get())?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let formatted = FormatString {
|
let args = AstConsoleArgs {
|
||||||
parts: ast_format.parts.clone(),
|
string: ast_console_args.string.clone(),
|
||||||
parameters,
|
parameters,
|
||||||
span: ast_format.span.clone(),
|
span: ast_console_args.span.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match &ast.function {
|
match &ast.function {
|
||||||
AstConsoleFunction::Debug(_) => AstConsoleFunction::Debug(formatted),
|
AstConsoleFunction::Debug(_) => AstConsoleFunction::Debug(args),
|
||||||
AstConsoleFunction::Error(_) => AstConsoleFunction::Error(formatted),
|
AstConsoleFunction::Error(_) => AstConsoleFunction::Error(args),
|
||||||
AstConsoleFunction::Log(_) => AstConsoleFunction::Log(formatted),
|
AstConsoleFunction::Log(_) => AstConsoleFunction::Log(args),
|
||||||
_ => return Err(ReducerError::impossible_console_assert_call(&ast_format.span)),
|
_ => return Err(ReducerError::impossible_console_assert_call(&ast_console_args.span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ast.function.clone(),
|
_ => ast.function.clone(),
|
||||||
|
Binary file not shown.
@ -559,7 +559,7 @@ unicode-character-escape = %s"\u{" 1*6hexadecimal-digit "}"
|
|||||||
; because string literals denote character arrays,
|
; because string literals denote character arrays,
|
||||||
; and arrays must not be empty.
|
; and arrays must not be empty.
|
||||||
|
|
||||||
string-literal = double-quote 1*string-literal-element double-quote
|
string-literal = double-quote *string-literal-element double-quote
|
||||||
|
|
||||||
string-literal-element = not-double-quote-or-backslash
|
string-literal-element = not-double-quote-or-backslash
|
||||||
/ simple-character-escape
|
/ simple-character-escape
|
||||||
|
5
parser/README.md
Normal file
5
parser/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# leo-parser
|
||||||
|
|
||||||
|
[![Crates.io](https://img.shields.io/crates/v/leo-parser.svg?color=neon)](https://crates.io/crates/leo-parser)
|
||||||
|
[![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](../AUTHORS)
|
||||||
|
[![License](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE.md)
|
@ -232,9 +232,9 @@ impl ParserContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns a [`FormatString`] AST node if the next tokens represent a formatted string.
|
/// Returns a [`ConsoleArgs`] AST node if the next tokens represent a formatted string.
|
||||||
///
|
///
|
||||||
pub fn parse_formatted_string(&mut self) -> SyntaxResult<FormatString> {
|
pub fn parse_console_args(&mut self) -> SyntaxResult<ConsoleArgs> {
|
||||||
let start_span;
|
let start_span;
|
||||||
let string = match self.expect_any()? {
|
let string = match self.expect_any()? {
|
||||||
SpannedToken {
|
SpannedToken {
|
||||||
@ -247,7 +247,7 @@ impl ParserContext {
|
|||||||
SpannedToken { token, span } => return Err(SyntaxError::unexpected_str(&token, "formatted string", &span)),
|
SpannedToken { token, span } => return Err(SyntaxError::unexpected_str(&token, "formatted string", &span)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let parts = FormatStringPart::from_string(string);
|
// let parts = FormatStringPart::from_string(string);
|
||||||
|
|
||||||
let mut parameters = Vec::new();
|
let mut parameters = Vec::new();
|
||||||
while self.eat(Token::Comma).is_some() {
|
while self.eat(Token::Comma).is_some() {
|
||||||
@ -255,8 +255,8 @@ impl ParserContext {
|
|||||||
parameters.push(param);
|
parameters.push(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(FormatString {
|
Ok(ConsoleArgs {
|
||||||
parts,
|
string,
|
||||||
span: &start_span + parameters.last().map(|x| x.span()).unwrap_or(&start_span),
|
span: &start_span + parameters.last().map(|x| x.span()).unwrap_or(&start_span),
|
||||||
parameters,
|
parameters,
|
||||||
})
|
})
|
||||||
@ -275,9 +275,9 @@ impl ParserContext {
|
|||||||
let expr = self.parse_expression()?;
|
let expr = self.parse_expression()?;
|
||||||
ConsoleFunction::Assert(expr)
|
ConsoleFunction::Assert(expr)
|
||||||
}
|
}
|
||||||
"debug" => ConsoleFunction::Debug(self.parse_formatted_string()?),
|
"debug" => ConsoleFunction::Debug(self.parse_console_args()?),
|
||||||
"error" => ConsoleFunction::Error(self.parse_formatted_string()?),
|
"error" => ConsoleFunction::Error(self.parse_console_args()?),
|
||||||
"log" => ConsoleFunction::Log(self.parse_formatted_string()?),
|
"log" => ConsoleFunction::Log(self.parse_console_args()?),
|
||||||
x => {
|
x => {
|
||||||
return Err(SyntaxError::unexpected_ident(
|
return Err(SyntaxError::unexpected_ident(
|
||||||
&x,
|
&x,
|
||||||
|
@ -280,7 +280,7 @@ impl Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == input.len() || i == 1 || !end {
|
if i == input.len() || !end {
|
||||||
return (0, None);
|
return (0, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- " --> compiler-test:4:17\n |\n 4 | console.log(\"{}\");\n | ^^^^\n |\n = function call expected 2 arguments, got 1"
|
- " --> compiler-test:4:17\n |\n 4 | console.log(\"{}\");\n | ^^^^\n |\n = Formatter given 1 containers and found 0 parameters"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- " --> compiler-test:4:17\n |\n 4 | console.log(\"\", 1u32);\n | ^\n |\n = unexpected token: '\"'"
|
- " --> compiler-test:4:17\n |\n 4 | console.log(\"\", 1u32);\n | ^^^^^^^^\n |\n = Formatter given 0 containers and found 1 parameters"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace: Token
|
namespace: Token
|
||||||
expectation: Pass
|
expectation: Pass
|
||||||
outputs:
|
outputs:
|
||||||
|
- "'\"\"' @ 1:1-3"
|
||||||
- "'\"string\"' @ 1:1-9"
|
- "'\"string\"' @ 1:1-9"
|
||||||
- "'\"another { } string\"' @ 1:1-21"
|
- "'\"another { } string\"' @ 1:1-21"
|
||||||
- "'\"{ ] [ ; a\"' @ 1:1-12"
|
- "'\"{ ] [ ; a\"' @ 1:1-12"
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
namespace: Token
|
namespace: Token
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- " --> test:1:1\n |\n 1 | \"\"\n | ^\n |\n = unexpected token: '\"'"
|
|
||||||
- " --> test:1:1\n |\n 1 | \"Hello world!\n | ^\n |\n = unexpected token: '\"'"
|
- " --> test:1:1\n |\n 1 | \"Hello world!\n | ^\n |\n = unexpected token: '\"'"
|
||||||
- " --> test:1:1\n |\n 1 | \"\\\"\n | ^\n |\n = unexpected token: '\"'"
|
- " --> test:1:1\n |\n 1 | \"\\\"\n | ^\n |\n = unexpected token: '\"'"
|
||||||
- " --> test:1:1\n |\n 1 | \"\\l\"\n | ^\n |\n = unexpected token: '\"'"
|
- " --> test:1:1\n |\n 1 | \"\\l\"\n | ^\n |\n = unexpected token: '\"'"
|
||||||
|
@ -16,9 +16,9 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Error:
|
Error:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
||||||
span:
|
span:
|
||||||
@ -38,11 +38,11 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Error:
|
Error:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":23,\\\"col_stop\\\":24,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":23,\\\"col_stop\\\":24,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":26,\\\"col_stop\\\":27,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":26,\\\"col_stop\\\":27,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.error(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
@ -63,8 +63,8 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Error:
|
Error:
|
||||||
parts:
|
string:
|
||||||
- Const: x
|
- Scalar: 120
|
||||||
parameters: []
|
parameters: []
|
||||||
span:
|
span:
|
||||||
line_start: 1
|
line_start: 1
|
||||||
@ -83,9 +83,9 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Debug:
|
Debug:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
||||||
span:
|
span:
|
||||||
@ -105,11 +105,11 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Debug:
|
Debug:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":23,\\\"col_stop\\\":24,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":23,\\\"col_stop\\\":24,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":26,\\\"col_stop\\\":27,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":26,\\\"col_stop\\\":27,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
@ -130,8 +130,8 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Debug:
|
Debug:
|
||||||
parts:
|
string:
|
||||||
- Const: x
|
- Scalar: 120
|
||||||
parameters: []
|
parameters: []
|
||||||
span:
|
span:
|
||||||
line_start: 1
|
line_start: 1
|
||||||
@ -150,9 +150,9 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Log:
|
Log:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":19,\\\"col_stop\\\":20,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":19,\\\"col_stop\\\":20,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}\\\\\\\", x);\\\"}\"}"
|
||||||
span:
|
span:
|
||||||
@ -172,11 +172,11 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Log:
|
Log:
|
||||||
parts:
|
string:
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
- Const: ""
|
- Scalar: 123
|
||||||
- Container
|
- Scalar: 125
|
||||||
parameters:
|
parameters:
|
||||||
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":24,\\\"col_stop\\\":25,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":24,\\\"col_stop\\\":25,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.log(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}"
|
||||||
@ -197,8 +197,8 @@ outputs:
|
|||||||
- Console:
|
- Console:
|
||||||
function:
|
function:
|
||||||
Log:
|
Log:
|
||||||
parts:
|
string:
|
||||||
- Const: x
|
- Scalar: 120
|
||||||
parameters: []
|
parameters: []
|
||||||
span:
|
span:
|
||||||
line_start: 1
|
line_start: 1
|
||||||
|
@ -3,6 +3,8 @@ namespace: Token
|
|||||||
expectation: Pass
|
expectation: Pass
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
""
|
||||||
|
|
||||||
"string"
|
"string"
|
||||||
|
|
||||||
"another { } string"
|
"another { } string"
|
||||||
|
@ -3,8 +3,6 @@ namespace: Token
|
|||||||
expectation: Fail
|
expectation: Fail
|
||||||
*/
|
*/
|
||||||
|
|
||||||
""
|
|
||||||
|
|
||||||
"Hello world!
|
"Hello world!
|
||||||
|
|
||||||
"\"
|
"\"
|
||||||
|
Loading…
Reference in New Issue
Block a user