merge testnet3

This commit is contained in:
collin 2022-05-13 12:33:35 -07:00
commit f6aa7a578a
401 changed files with 6314 additions and 14884 deletions

6
Cargo.lock generated
View File

@ -391,9 +391,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.1.17"
version = "3.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47582c09be7c8b32c0ab3a6181825ababb713fde6fff20fc573a3870dd45c6a0"
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
dependencies = [
"atty",
"bitflags",
@ -1255,7 +1255,7 @@ dependencies = [
"ansi_term",
"assert_cmd",
"backtrace",
"clap 3.1.17",
"clap 3.1.18",
"color-backtrace",
"colored",
"console",

View File

@ -17,7 +17,7 @@
use leo_errors::Result;
use leo_span::{Span, Symbol};
use crate::Node;
use crate::{simple_node_impl, Node};
use serde::{
de::{
Visitor, {self},
@ -43,15 +43,7 @@ pub struct Identifier {
pub span: Span,
}
impl Node for Identifier {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
simple_node_impl!(Identifier);
impl Identifier {
/// Constructs a new identifier with `name` and a default span.

View File

@ -120,12 +120,4 @@ impl fmt::Display for BinaryExpression {
}
}
impl Node for BinaryExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(BinaryExpression);

View File

@ -41,12 +41,4 @@ impl fmt::Display for CallExpression {
}
}
impl Node for CallExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(CallExpression);

View File

@ -29,12 +29,4 @@ impl fmt::Display for ErrExpression {
}
}
impl Node for ErrExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ErrExpression);

View File

@ -54,9 +54,9 @@ pub enum Expression {
}
impl Node for Expression {
fn span(&self) -> &Span {
fn span(&self) -> Span {
use Expression::*;
match &self {
match self {
Identifier(n) => n.span(),
Value(n) => n.span(),
Binary(n) => n.span(),

View File

@ -35,12 +35,4 @@ impl fmt::Display for TernaryExpression {
}
}
impl Node for TernaryExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(TernaryExpression);

View File

@ -52,12 +52,4 @@ impl fmt::Display for UnaryExpression {
}
}
impl Node for UnaryExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(UnaryExpression);

View File

@ -64,7 +64,7 @@ impl fmt::Display for ValueExpression {
}
impl Node for ValueExpression {
fn span(&self) -> &Span {
fn span(&self) -> Span {
use ValueExpression::*;
match &self {
Address(_, span)
@ -72,11 +72,11 @@ impl Node for ValueExpression {
| Field(_, span)
| Integer(_, _, span)
| Scalar(_, span)
| String(_, span) => span,
Char(character) => &character.span,
| String(_, span) => *span,
Char(character) => character.span,
Group(group) => match &**group {
GroupValue::Single(_, span) => span,
GroupValue::Tuple(tuple) => &tuple.span,
GroupValue::Single(_, span) => *span,
GroupValue::Tuple(tuple) => tuple.span,
},
}
}

View File

@ -82,12 +82,4 @@ impl fmt::Debug for Function {
}
}
impl Node for Function {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(Function);

View File

@ -87,12 +87,4 @@ impl fmt::Debug for FunctionInputVariable {
}
}
impl Node for FunctionInputVariable {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(FunctionInputVariable);

View File

@ -70,10 +70,10 @@ impl PartialEq for FunctionInput {
impl Eq for FunctionInput {}
impl Node for FunctionInput {
fn span(&self) -> &Span {
fn span(&self) -> Span {
use FunctionInput::*;
match self {
Variable(variable) => &variable.span,
Variable(variable) => variable.span,
}
}

View File

@ -38,7 +38,7 @@ impl TryFrom<(Type, Expression)> for InputValue {
match (type_, value) {
(Type::Address, ValueExpression::Address(value, _)) => Self::Address(value),
(Type::Boolean, ValueExpression::Boolean(value, span)) => {
let bool_value = value.parse::<bool>().map_err(|_| ParserError::unexpected_eof(&span))?; // TODO: change error
let bool_value = value.parse::<bool>().map_err(|_| ParserError::unexpected_eof(span))?; // TODO: change error
Self::Boolean(bool_value)
}
(Type::Char, ValueExpression::Char(value)) => Self::Char(value),
@ -48,7 +48,7 @@ impl TryFrom<(Type, Expression)> for InputValue {
if expected == actual {
Self::Integer(expected, value)
} else {
return Err(InputError::unexpected_type(expected.to_string(), actual, &span).into());
return Err(InputError::unexpected_type(expected.to_string(), actual, span).into());
}
}
(x, y) => {

View File

@ -35,7 +35,7 @@ impl TryFrom<InputAst> for ProgramInput {
sym::registers => &mut registers,
_ => {
return Err(
InputError::unexpected_section(&["main", "registers"], section.name, &section.span).into(),
InputError::unexpected_section(&["main", "registers"], section.name, section.span).into(),
)
}
};

View File

@ -39,7 +39,7 @@ impl TryFrom<InputAst> for ProgramState {
return Err(InputError::unexpected_section(
&["state", "record", "state_leaf"],
section.name,
&section.span,
section.span,
)
.into());
}

View File

@ -21,8 +21,23 @@ pub trait Node:
std::fmt::Debug + std::fmt::Display + Clone + PartialEq + Eq + serde::Serialize + serde::de::DeserializeOwned
{
/// Returns the span of the node.
fn span(&self) -> &Span;
fn span(&self) -> Span;
/// Sets the span of the node.
fn set_span(&mut self, span: Span);
}
#[macro_export]
macro_rules! simple_node_impl {
($ty:ty) => {
impl Node for $ty {
fn span(&self) -> Span {
self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
};
}

View File

@ -206,7 +206,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
pub fn reduce_iteration(&mut self, iteration: &IterationStatement) -> Result<IterationStatement> {
let variable = self.reduce_identifier(&iteration.variable)?;
let type_ = self.reduce_type(&iteration.type_, iteration.span())?;
let type_ = self.reduce_type(&iteration.type_, &iteration.span())?;
let start = self.reduce_expression(&iteration.start)?;
let stop = self.reduce_expression(&iteration.stop)?;
let block = self.reduce_block(&iteration.block)?;
@ -227,13 +227,13 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let formatted = ConsoleArgs {
string: args.string.clone(),
parameters,
span: args.span.clone(),
span: args.span,
};
match &console_function_call.function {
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
_ => return Err(AstError::impossible_console_assert_call(&args.span).into()),
_ => return Err(AstError::impossible_console_assert_call(args.span).into()),
}
}
};

View File

@ -43,7 +43,7 @@ pub trait ReconstructingReducer {
fn reduce_identifier(&mut self, identifier: &Identifier) -> Result<Identifier> {
Ok(Identifier {
name: identifier.name,
span: identifier.span.clone(),
span: identifier.span,
})
}
@ -51,7 +51,7 @@ pub trait ReconstructingReducer {
Ok(GroupTuple {
x: group_tuple.x.clone(),
y: group_tuple.y.clone(),
span: group_tuple.span.clone(),
span: group_tuple.span,
})
}
@ -60,10 +60,7 @@ pub trait ReconstructingReducer {
}
fn reduce_string(&mut self, string: &[Char], span: &Span) -> Result<Expression> {
Ok(Expression::Value(ValueExpression::String(
string.to_vec(),
span.clone(),
)))
Ok(Expression::Value(ValueExpression::String(string.to_vec(), *span)))
}
fn reduce_value(&mut self, _value: &ValueExpression, new: Expression) -> Result<Expression> {
@ -81,7 +78,7 @@ pub trait ReconstructingReducer {
left: Box::new(left),
right: Box::new(right),
op,
span: binary.span.clone(),
span: binary.span,
})
}
@ -94,7 +91,7 @@ pub trait ReconstructingReducer {
Ok(UnaryExpression {
inner: Box::new(inner),
op,
span: unary.span.clone(),
span: unary.span,
})
}
@ -109,7 +106,7 @@ pub trait ReconstructingReducer {
condition: Box::new(condition),
if_true: Box::new(if_true),
if_false: Box::new(if_false),
span: ternary.span.clone(),
span: ternary.span,
})
}
@ -122,7 +119,7 @@ pub trait ReconstructingReducer {
Ok(CallExpression {
function: Box::new(function),
arguments,
span: call.span.clone(),
span: call.span,
})
}
@ -134,7 +131,7 @@ pub trait ReconstructingReducer {
fn reduce_return(&mut self, return_statement: &ReturnStatement, expression: Expression) -> Result<ReturnStatement> {
Ok(ReturnStatement {
expression,
span: return_statement.span.clone(),
span: return_statement.span,
})
}
@ -142,7 +139,7 @@ pub trait ReconstructingReducer {
Ok(VariableName {
mutable: variable_name.mutable,
identifier,
span: variable_name.span.clone(),
span: variable_name.span,
})
}
@ -158,7 +155,7 @@ pub trait ReconstructingReducer {
variable_names,
type_,
value,
span: definition.span.clone(),
span: definition.span,
})
}
@ -175,7 +172,7 @@ pub trait ReconstructingReducer {
Ok(Assignee {
identifier,
accesses,
span: assignee.span.clone(),
span: assignee.span,
})
}
@ -189,7 +186,7 @@ pub trait ReconstructingReducer {
operation: assign.operation,
assignee,
value,
span: assign.span.clone(),
span: assign.span,
})
}
@ -204,7 +201,7 @@ pub trait ReconstructingReducer {
condition,
block,
next: statement.map(|statement| Box::new(statement)),
span: conditional.span.clone(),
span: conditional.span,
})
}
@ -224,14 +221,14 @@ pub trait ReconstructingReducer {
stop,
inclusive: iteration.inclusive,
block,
span: iteration.span.clone(),
span: iteration.span,
})
}
fn reduce_console(&mut self, console: &ConsoleStatement, function: ConsoleFunction) -> Result<ConsoleStatement> {
Ok(ConsoleStatement {
function,
span: console.span.clone(),
span: console.span,
})
}
@ -242,14 +239,14 @@ pub trait ReconstructingReducer {
) -> Result<ExpressionStatement> {
Ok(ExpressionStatement {
expression,
span: expression_statement.span.clone(),
span: expression_statement.span,
})
}
fn reduce_block(&mut self, block: &Block, statements: Vec<Statement>) -> Result<Block> {
Ok(Block {
statements,
span: block.span.clone(),
span: block.span,
})
}
@ -278,7 +275,7 @@ pub trait ReconstructingReducer {
identifier,
variable.mode(),
type_,
variable.span.clone(),
variable.span,
))
}
@ -305,7 +302,7 @@ pub trait ReconstructingReducer {
output,
block,
core_mapping: function.core_mapping.clone(),
span: function.span.clone(),
span: function.span,
})
}
}

View File

@ -100,12 +100,4 @@ impl fmt::Display for AssignStatement {
}
}
impl Node for AssignStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(AssignStatement);

View File

@ -43,12 +43,4 @@ impl fmt::Display for Block {
}
}
impl Node for Block {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(Block);

View File

@ -43,12 +43,4 @@ impl fmt::Display for ConditionalStatement {
}
}
impl Node for ConditionalStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ConditionalStatement);

View File

@ -46,12 +46,4 @@ impl fmt::Display for ConsoleArgs {
}
}
impl Node for ConsoleArgs {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ConsoleArgs);

View File

@ -45,10 +45,10 @@ impl fmt::Display for ConsoleFunction {
}
impl Node for ConsoleFunction {
fn span(&self) -> &Span {
fn span(&self) -> Span {
match self {
ConsoleFunction::Assert(assert) => assert.span(),
ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => &formatted.span,
ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => formatted.span,
}
}

View File

@ -41,12 +41,4 @@ impl fmt::Debug for ConsoleStatement {
}
}
impl Node for ConsoleStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ConsoleStatement);

View File

@ -64,12 +64,4 @@ impl fmt::Display for DefinitionStatement {
}
}
impl Node for DefinitionStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(DefinitionStatement);

View File

@ -37,12 +37,4 @@ impl fmt::Display for VariableName {
}
}
impl Node for VariableName {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(VariableName);

View File

@ -35,12 +35,4 @@ impl fmt::Display for ExpressionStatement {
}
}
impl Node for ExpressionStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ExpressionStatement);

View File

@ -51,12 +51,4 @@ impl fmt::Display for IterationStatement {
}
}
impl Node for IterationStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(IterationStatement);

View File

@ -35,12 +35,4 @@ impl fmt::Display for ReturnStatement {
}
}
impl Node for ReturnStatement {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
crate::simple_node_impl!(ReturnStatement);

View File

@ -59,9 +59,9 @@ impl fmt::Display for Statement {
}
impl Node for Statement {
fn span(&self) -> &Span {
fn span(&self) -> Span {
use Statement::*;
match &self {
match self {
Return(n) => n.span(),
Definition(n) => n.span(),
Assign(n) => n.span(),

View File

@ -37,7 +37,7 @@ version = "1.5.3"
[dependencies.sha2]
version = "0.10"
[dev-dependencies.leo-span]
[dependencies.leo-span]
path = "../../leo/span"
version = "1.5.3"

View File

@ -31,6 +31,8 @@ use leo_errors::emitter::Handler;
use leo_errors::{CompilerError, Result};
pub use leo_passes::SymbolTable;
use leo_passes::*;
use leo_span::source_map::FileName;
use leo_span::symbol::with_session_globals;
use sha2::{Digest, Sha256};
use std::fs;
@ -77,13 +79,12 @@ impl<'a> Compiler<'a> {
}
// Parses and stores a program file content from a string, constructs a syntax tree, and generates a program.
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<()> {
pub fn parse_program_from_string(&mut self, program_string: &str, name: FileName) -> Result<()> {
// Register the source (`program_string`) in the source map.
let prg_sf = with_session_globals(|s| s.source_map.new_source(program_string, name));
// Use the parser to construct the abstract syntax tree (ast).
let ast: leo_ast::Ast = leo_parser::parse_ast(
self.handler,
self.main_file_path.to_str().unwrap_or_default(),
program_string,
)?;
let ast: leo_ast::Ast = leo_parser::parse_ast(self.handler, &prg_sf.src, prg_sf.start_pos)?;
// Write the AST snapshot post parsing.
ast.to_json_file_without_keys(self.output_directory.clone(), "initial_ast.json", &["span"])?;
@ -96,31 +97,24 @@ impl<'a> Compiler<'a> {
pub fn parse_program(&mut self) -> Result<()> {
// Load the program file.
let program_string = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::file_read_error(self.main_file_path.clone(), e))?;
.map_err(|e| CompilerError::file_read_error(&self.main_file_path, e))?;
self.parse_program_from_string(&program_string)
}
/// Parses and stores the input file, constructs a syntax tree, and generates a program input.
pub fn parse_input_from_string(&mut self, input_file_path: PathBuf, input_string: &str) -> Result<()> {
let input_ast =
leo_parser::parse_input(self.handler, input_file_path.to_str().unwrap_or_default(), input_string)?;
input_ast.to_json_file_without_keys(self.output_directory.clone(), "inital_input_ast.json", &["span"])?;
self.input_ast = Some(input_ast);
Ok(())
self.parse_program_from_string(&program_string, FileName::Real(self.main_file_path.clone()))
}
/// Parses and stores the input file, constructs a syntax tree, and generates a program input.
pub fn parse_input(&mut self, input_file_path: PathBuf) -> Result<()> {
// Load the input file if it exists.
if input_file_path.exists() {
let input_string = fs::read_to_string(&input_file_path)
.map_err(|e| CompilerError::file_read_error(input_file_path.clone(), e))?;
// Load the input file into the source map.
let input_sf = with_session_globals(|s| s.source_map.load_file(&input_file_path))
.map_err(|e| CompilerError::file_read_error(&input_file_path, e))?;
self.parse_input_from_string(input_file_path, &input_string)?;
// Parse and serialize it.
let input_ast = leo_parser::parse_input(self.handler, &input_sf.src, input_sf.start_pos)?;
input_ast.to_json_file_without_keys(self.output_directory.clone(), "inital_input_ast.json", &["span"])?;
self.input_ast = Some(input_ast);
}
Ok(())
}

View File

@ -28,7 +28,7 @@ use leo_errors::{
LeoError, LeoWarning,
};
use leo_passes::SymbolTable;
use leo_span::symbol::create_session_if_not_set_then;
use leo_span::{source_map::FileName, symbol::create_session_if_not_set_then};
use leo_test_framework::{
runner::{Namespace, ParseType, Runner},
Test,
@ -48,8 +48,9 @@ fn parse_program<'a>(
program_string: &str,
cwd: Option<PathBuf>,
) -> Result<Compiler<'a>, LeoError> {
let mut compiler = new_compiler(handler, cwd.unwrap_or_else(|| "compiler-test".into()));
compiler.parse_program_from_string(program_string)?;
let mut compiler = new_compiler(handler, cwd.clone().unwrap_or_else(|| "compiler-test".into()));
let name = cwd.map_or_else(|| FileName::Custom("compiler-test".into()), FileName::Real);
compiler.parse_program_from_string(program_string, name)?;
Ok(compiler)
}

View File

@ -16,14 +16,15 @@
use leo_ast::Ast;
use leo_errors::emitter::Handler;
use leo_span::symbol::create_session_if_not_set_then;
use leo_span::{source_map::FileName, symbol::create_session_if_not_set_then};
use criterion::{criterion_group, criterion_main, Criterion};
use std::time::Duration;
fn parse_ast(path: &str, input: &str) -> Ast {
create_session_if_not_set_then(|_| {
leo_parser::parse_ast(&Handler::default(), path, input).expect("failed to parse benchmark")
create_session_if_not_set_then(|s| {
let sf = s.source_map.new_source(input, FileName::Custom(path.into()));
leo_parser::parse_ast(&Handler::default(), &sf.src, sf.start_pos).expect("failed to parse benchmark")
})
}
@ -34,6 +35,8 @@ macro_rules! bench {
concat!("./", $file_name, ".leo"),
include_str!(concat!("./", $file_name, ".leo"),),
);
// TODO(Centril): This benchmark seems like it actually does nothing
// but take a reference to `&ast`, which should be optimized out?
c.bench_function(concat!("Ast::", $file_name), |b| b.iter(|| &ast));
}
};

View File

@ -44,11 +44,14 @@ struct Opt {
fn main() -> Result<(), String> {
let opt = Opt::from_args();
let input_string = fs::read_to_string(&opt.input_path).expect("failed to open an input file");
let input_tree = create_session_if_not_set_then(|_| {
let input_tree = create_session_if_not_set_then(|s| {
let input_string = s
.source_map
.load_file(&opt.input_path)
.expect("failed to open an input file");
Handler::with(|handler| {
let input =
leo_parser::parse_program_inputs(handler, input_string.clone(), opt.input_path.to_str().unwrap())?;
let input = leo_parser::parse_program_inputs(handler, &input_string.src, input_string.start_pos)?;
input.to_json_string()
})
.map_err(|e| e.to_string())

View File

@ -42,12 +42,12 @@ struct Opt {
fn main() -> Result<(), String> {
let opt = Opt::from_args();
let code = fs::read_to_string(&opt.input_path).expect("failed to open file");
// Parses the Leo file constructing an ast which is then serialized.
let serialized_leo_tree = create_session_if_not_set_then(|_| {
let serialized_leo_tree = create_session_if_not_set_then(|s| {
let code = s.source_map.load_file(&opt.input_path).expect("failed to open file");
Handler::with(|h| {
let ast = leo_parser::parse_ast(h, opt.input_path.to_str().unwrap(), &code)?;
let ast = leo_parser::parse_ast(h, &code.src, code.start_pos)?;
let json = Ast::to_json_string(&ast)?;
println!("{}", json);
Ok(json)

View File

@ -23,6 +23,7 @@
#![doc = include_str!("../README.md")]
pub(crate) mod tokenizer;
use leo_span::span::BytePos;
pub use tokenizer::KEYWORD_TOKENS;
pub(crate) use tokenizer::*;
@ -37,18 +38,13 @@ use leo_errors::Result;
mod test;
/// Creates a new AST from a given file path and source code text.
pub fn parse_ast<T: AsRef<str>, Y: AsRef<str>>(handler: &Handler, path: T, source: Y) -> Result<Ast> {
Ok(Ast::new(parser::parse(handler, path.as_ref(), source.as_ref())?))
pub fn parse_ast(handler: &Handler, source: &str, start_pos: BytePos) -> Result<Ast> {
Ok(Ast::new(parser::parse(handler, source, start_pos)?))
}
/// Parses program inputs from from the input file path and state file path
pub fn parse_program_inputs<T: AsRef<str>, Y: AsRef<str>>(
handler: &Handler,
input_string: T,
input_path: Y,
) -> Result<Input> {
let program_input: ProgramInput =
parser::parse_input(handler, input_path.as_ref(), input_string.as_ref())?.try_into()?;
pub fn parse_program_inputs(handler: &Handler, input_string: &str, start_pos: BytePos) -> Result<Input> {
let program_input: ProgramInput = parser::parse_input(handler, input_string, start_pos)?.try_into()?;
Ok(Input {
program_input,

View File

@ -39,11 +39,14 @@ pub struct ParserContext<'a> {
pub(crate) prev_token: SpannedToken,
/// true if parsing an expression for if and loop statements -- means circuit inits are not legal
pub(crate) disallow_circuit_construction: bool,
/// HACK(Centril): Place to store a dummy EOF.
/// Exists to appease borrow checker for now.
dummy_eof: SpannedToken,
}
/// Dummy span used to appease borrow checker.
const DUMMY_EOF: SpannedToken = SpannedToken {
token: Token::Eof,
span: Span::dummy(),
};
impl<'a> ParserContext<'a> {
/// Returns a new [`ParserContext`] type given a vector of tokens.
pub fn new(handler: &'a Handler, mut tokens: Vec<SpannedToken>) -> Self {
@ -53,14 +56,9 @@ impl<'a> ParserContext<'a> {
tokens.reverse();
let token = SpannedToken::dummy();
let dummy_eof = SpannedToken {
token: Token::Eof,
span: token.span.clone(),
};
let mut p = Self {
handler,
disallow_circuit_construction: false,
dummy_eof,
prev_token: token.clone(),
token,
tokens,
@ -80,9 +78,9 @@ impl<'a> ParserContext<'a> {
}
// Extract next token, or `Eof` if there was none.
let next_token = self.tokens.pop().unwrap_or_else(|| SpannedToken {
let next_token = self.tokens.pop().unwrap_or(SpannedToken {
token: Token::Eof,
span: self.token.span.clone(),
span: self.token.span,
});
// Set the new token.
@ -108,11 +106,11 @@ impl<'a> ParserContext<'a> {
}
let idx = match self.tokens.len().checked_sub(dist) {
None => return looker(&self.dummy_eof),
None => return looker(&DUMMY_EOF),
Some(idx) => idx,
};
looker(self.tokens.get(idx).unwrap_or(&self.dummy_eof))
looker(self.tokens.get(idx).unwrap_or(&DUMMY_EOF))
}
/// Emit the error `err`.
@ -132,7 +130,7 @@ impl<'a> ParserContext<'a> {
/// At the previous token, return and make an identifier with `name`.
fn mk_ident_prev(&self, name: Symbol) -> Identifier {
let span = self.prev_token.span.clone();
let span = self.prev_token.span;
Identifier { name, span }
}
@ -161,7 +159,7 @@ impl<'a> ParserContext<'a> {
/// Expects an [`Identifier`], or errors.
pub fn expect_ident(&mut self) -> Result<Identifier> {
self.eat_identifier()
.ok_or_else(|| ParserError::unexpected_str(&self.token.token, "ident", &self.token.span).into())
.ok_or_else(|| ParserError::unexpected_str(&self.token.token, "ident", self.token.span).into())
}
/// Returns a reference to the next token if it is a [`GroupCoordinate`], or [None] if
@ -170,11 +168,11 @@ impl<'a> ParserContext<'a> {
let (advanced, gc) = self.look_ahead(*dist, |t0| match &t0.token {
Token::Add => Some((1, GroupCoordinate::SignHigh)),
Token::Minus => self.look_ahead(*dist + 1, |t1| match &t1.token {
Token::Int(value) => Some((2, GroupCoordinate::Number(format!("-{}", value), t1.span.clone()))),
Token::Int(value) => Some((2, GroupCoordinate::Number(format!("-{}", value), t1.span))),
_ => Some((1, GroupCoordinate::SignLow)),
}),
Token::Underscore => Some((1, GroupCoordinate::Inferred)),
Token::Int(value) => Some((1, GroupCoordinate::Number(value.clone(), t0.span.clone()))),
Token::Int(value) => Some((1, GroupCoordinate::Number(value.clone(), t0.span))),
_ => None,
})?;
*dist += advanced;
@ -200,7 +198,7 @@ impl<'a> ParserContext<'a> {
let mut dist = 1; // 0th is `(` so 1st is first gc's start.
let first_gc = self.peek_group_coordinate(&mut dist)?;
let check_ahead = |d, token: &_| self.look_ahead(d, |t| (&t.token == token).then(|| t.span.clone()));
let check_ahead = |d, token: &_| self.look_ahead(d, |t| (&t.token == token).then(|| t.span));
// Peek at `,`.
check_ahead(dist, &Token::Comma)?;
@ -228,7 +226,7 @@ impl<'a> ParserContext<'a> {
self.bump();
}
if let Err(e) = assert_no_whitespace(&right_paren_span, &end_span, &format!("({},{})", gt.x, gt.y), "group") {
if let Err(e) = assert_no_whitespace(right_paren_span, end_span, &format!("({},{})", gt.x, gt.y), "group") {
return Some(Err(e));
}
@ -252,13 +250,13 @@ impl<'a> ParserContext<'a> {
/// Returns an unexpected error at the current token.
fn unexpected<T>(&self, expected: impl Display) -> Result<T> {
Err(ParserError::unexpected(&self.token.token, expected, &self.token.span).into())
Err(ParserError::unexpected(&self.token.token, expected, self.token.span).into())
}
/// Eats the expected `token`, or errors.
pub fn expect(&mut self, token: &Token) -> Result<Span> {
if self.eat(token) {
Ok(self.prev_token.span.clone())
Ok(self.prev_token.span)
} else {
self.unexpected(token)
}
@ -267,7 +265,7 @@ impl<'a> ParserContext<'a> {
/// Eats one of the expected `tokens`, or errors.
pub fn expect_any(&mut self, tokens: &[Token]) -> Result<Span> {
if self.eat_any(tokens) {
Ok(self.prev_token.span.clone())
Ok(self.prev_token.span)
} else {
self.unexpected(tokens.iter().map(|x| format!("'{}'", x)).collect::<Vec<_>>().join(", "))
}

View File

@ -155,10 +155,12 @@ impl ParserContext<'_> {
///
/// Otherwise, tries to parse the next token using [`parse_additive_expression`].
pub fn parse_ordering_expression(&mut self) -> Result<Expression> {
self.parse_bin_expr(
&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq],
Self::parse_additive_expression,
)
let mut expr = self.parse_additive_expression()?;
if let Some(op) = self.eat_bin_op(&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq]) {
let right = self.parse_additive_expression()?;
expr = Self::bin_expr(expr, right, op);
}
Ok(expr)
}
/// Returns an [`Expression`] AST node if the next tokens represent a
@ -204,12 +206,12 @@ impl ParserContext<'_> {
Token::Minus => UnaryOperation::Negate,
_ => unreachable!("parse_unary_expression_ shouldn't produce this"),
};
ops.push((operation, self.prev_token.span.clone()));
ops.push((operation, self.prev_token.span));
}
let mut inner = self.parse_postfix_expression()?;
for (op, op_span) in ops.into_iter().rev() {
inner = Expression::Unary(UnaryExpression {
span: &op_span + inner.span(),
span: op_span + inner.span(),
op,
inner: Box::new(inner),
});
@ -229,7 +231,7 @@ impl ParserContext<'_> {
loop {
if self.eat(&Token::Dot) {
let curr = &self.token;
return Err(ParserError::unexpected_str(&curr.token, "int or ident", &curr.span).into());
return Err(ParserError::unexpected_str(&curr.token, "int or ident", curr.span).into());
}
if !self.check(&Token::LeftParen) {
@ -238,7 +240,7 @@ impl ParserContext<'_> {
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
expr = Expression::Call(CallExpression {
span: expr.span() + &span,
span: expr.span() + span,
function: Box::new(expr),
arguments,
});
@ -260,7 +262,7 @@ impl ParserContext<'_> {
if !trailing && tuple.len() == 1 {
Ok(tuple.remove(0))
} else {
Err(ParserError::unexpected("A tuple expression.", "A valid expression.", &span).into())
Err(ParserError::unexpected("A tuple expression.", "A valid expression.", span).into())
}
}
@ -281,9 +283,9 @@ impl ParserContext<'_> {
Ok(match token {
Token::Int(value) => {
let suffix_span = self.token.span.clone();
let full_span = &span + &suffix_span;
let assert_no_whitespace = |x| assert_no_whitespace(&span, &suffix_span, &value, x);
let suffix_span = self.token.span;
let full_span = span + suffix_span;
let assert_no_whitespace = |x| assert_no_whitespace(span, suffix_span, &value, x);
match self.eat_any(INT_TYPES).then(|| &self.prev_token.token) {
// Literal followed by `field`, e.g., `42field`.
Some(Token::Field) => {
@ -306,7 +308,7 @@ impl ParserContext<'_> {
let int_ty = Self::token_to_int_type(suffix).expect("unknown int type token");
Expression::Value(ValueExpression::Integer(int_ty, value, full_span))
}
None => return Err(ParserError::implicit_values_not_allowed(value, &span).into()),
None => return Err(ParserError::implicit_values_not_allowed(value, span).into()),
}
}
Token::True => Expression::Value(ValueExpression::Boolean("true".into(), span)),
@ -327,7 +329,7 @@ impl ParserContext<'_> {
span,
}),
token => {
return Err(ParserError::unexpected_str(token, "expression", &span).into());
return Err(ParserError::unexpected_str(token, "expression", span).into());
}
})
}

View File

@ -26,7 +26,7 @@ impl ParserContext<'_> {
while self.has_next() {
match &self.token.token {
Token::Ident(sym::test) => return Err(ParserError::test_function(&self.token.span).into()),
Token::Ident(sym::test) => return Err(ParserError::test_function(self.token.span).into()),
// Const functions share the first token with the global Const.
Token::Const if self.peek_is_function() => {
let (id, function) = self.parse_function_declaration()?;
@ -54,17 +54,17 @@ impl ParserContext<'_> {
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
.join(", "),
&token.span,
token.span,
)
}
/// Returns a [`ParamMode`] AST node if the next tokens represent a function parameter mode.
pub fn parse_function_parameter_mode(&mut self) -> Result<ParamMode> {
let public = self.eat(&Token::Public).then(|| self.prev_token.span.clone());
let constant = self.eat(&Token::Constant).then(|| self.prev_token.span.clone());
let const_ = self.eat(&Token::Const).then(|| self.prev_token.span.clone());
let public = self.eat(&Token::Public).then(|| self.prev_token.span);
let constant = self.eat(&Token::Constant).then(|| self.prev_token.span);
let const_ = self.eat(&Token::Const).then(|| self.prev_token.span);
if let Some(span) = &const_ {
if let Some(span) = const_ {
self.emit_warning(ParserWarning::const_parameter_or_input(span));
}
@ -74,10 +74,10 @@ impl ParserContext<'_> {
(None, None, None) => Ok(ParamMode::Private),
(Some(_), None, None) => Ok(ParamMode::Public),
(Some(m1), Some(m2), None) | (Some(m1), None, Some(m2)) | (None, Some(m1), Some(m2)) => {
Err(ParserError::inputs_multiple_variable_types_specified(&(m1 + m2)).into())
Err(ParserError::inputs_multiple_variable_types_specified(m1 + m2).into())
}
(Some(m1), Some(m2), Some(m3)) => {
Err(ParserError::inputs_multiple_variable_types_specified(&(m1 + m2 + m3)).into())
Err(ParserError::inputs_multiple_variable_types_specified(m1 + m2 + m3).into())
}
}
}
@ -90,7 +90,7 @@ impl ParserContext<'_> {
let name = self.expect_ident()?;
if let Some(mutable) = &mutable {
self.emit_err(ParserError::mut_function_input(&(&mutable.span + &name.span)));
self.emit_err(ParserError::mut_function_input(mutable.span + name.span));
}
self.expect(&Token::Colon)?;
@ -126,7 +126,7 @@ impl ParserContext<'_> {
identifier: name,
input: inputs,
output,
span: start + block.span.clone(),
span: start + block.span,
block,
core_mapping: <_>::default(),
},

View File

@ -27,7 +27,7 @@ impl ParserContext<'_> {
if self.check(&Token::LeftSquare) {
sections.push(self.parse_section()?);
} else {
return Err(ParserError::unexpected_token(self.token.token.clone(), &self.token.span).into());
return Err(ParserError::unexpected_token(self.token.token.clone(), self.token.span).into());
}
}

View File

@ -27,6 +27,7 @@ use leo_errors::{ParserError, Result};
use leo_span::Span;
use indexmap::IndexMap;
use leo_span::span::BytePos;
use std::unreachable;
mod context;
@ -38,27 +39,25 @@ pub mod input;
pub mod statement;
pub mod type_;
pub(crate) fn assert_no_whitespace(left_span: &Span, right_span: &Span, left: &str, right: &str) -> Result<()> {
if left_span.col_stop != right_span.col_start {
let mut error_span = left_span + right_span;
error_span.col_start = left_span.col_stop - 1;
error_span.col_stop = right_span.col_start - 1;
return Err(ParserError::unexpected_whitespace(left, right, &error_span).into());
pub(crate) fn assert_no_whitespace(left_span: Span, right_span: Span, left: &str, right: &str) -> Result<()> {
if left_span.hi != right_span.lo {
let error_span = Span::new(left_span.hi, right_span.lo); // The span between them.
return Err(ParserError::unexpected_whitespace(left, right, error_span).into());
}
Ok(())
}
/// Creates a new program from a given file path and source code text.
pub fn parse(handler: &Handler, path: &str, source: &str) -> Result<Program> {
let mut tokens = ParserContext::new(handler, crate::tokenize(path, source)?);
pub fn parse(handler: &Handler, source: &str, start_pos: BytePos) -> Result<Program> {
let mut tokens = ParserContext::new(handler, crate::tokenize(source, start_pos)?);
tokens.parse_program()
}
/// Parses an input file at the given file `path` and `source` code text.
pub fn parse_input<T: AsRef<str>, Y: AsRef<str>>(handler: &Handler, path: T, source: Y) -> Result<InputAst> {
let mut tokens = ParserContext::new(handler, crate::tokenize(path.as_ref(), source.as_ref())?);
pub fn parse_input(handler: &Handler, source: &str, start_pos: BytePos) -> Result<InputAst> {
let mut tokens = ParserContext::new(handler, crate::tokenize(source, start_pos)?);
tokens.parse_input()
}

View File

@ -27,19 +27,16 @@ impl ParserContext<'_> {
pub fn construct_assignee_access(expr: Expression, _accesses: &mut [AssigneeAccess]) -> Result<Identifier> {
match expr {
Expression::Identifier(id) => Ok(id),
_ => return Err(ParserError::invalid_assignment_target(expr.span()).into()),
_ => Err(ParserError::invalid_assignment_target(expr.span()).into()),
}
}
/// Returns an [`Assignee`] AST node from the given [`Expression`] AST node with accesses.
pub fn construct_assignee(expr: Expression) -> Result<Assignee> {
let expr_span = expr.span().clone();
let mut accesses = Vec::new();
let identifier = Self::construct_assignee_access(expr, &mut accesses)?;
Ok(Assignee {
span: expr_span,
identifier,
span: expr.span(),
identifier: Self::construct_assignee_access(expr, &mut accesses)?,
accesses,
})
}
@ -66,7 +63,7 @@ impl ParserContext<'_> {
let assignee = Self::construct_assignee(expr)?;
self.expect(&Token::Semicolon)?;
Ok(Statement::Assign(Box::new(AssignStatement {
span: &assignee.span + value.span(),
span: assignee.span + value.span(),
assignee,
// Currently only `=` so this is alright.
operation: AssignOperation::Assign,
@ -75,7 +72,7 @@ impl ParserContext<'_> {
} else {
self.expect(&Token::Semicolon)?;
Ok(Statement::Expression(ExpressionStatement {
span: expr.span().clone(),
span: expr.span(),
expression: expr,
}))
}
@ -89,7 +86,7 @@ impl ParserContext<'_> {
loop {
if self.eat(&Token::RightCurly) {
return Ok(Block {
span: &start + &self.prev_token.span,
span: start + self.prev_token.span,
statements,
});
}
@ -103,7 +100,7 @@ impl ParserContext<'_> {
let start = self.expect(&Token::Return)?;
let expression = self.parse_expression()?;
self.expect(&Token::Semicolon)?;
let span = &start + expression.span();
let span = start + expression.span();
Ok(ReturnStatement { span, expression })
}
@ -125,7 +122,7 @@ impl ParserContext<'_> {
};
Ok(ConditionalStatement {
span: &start + next.as_ref().map(|x| x.span()).unwrap_or(&body.span),
span: start + next.as_ref().map(|x| x.span()).unwrap_or(body.span),
condition: expr,
block: body,
next,
@ -151,7 +148,7 @@ impl ParserContext<'_> {
let block = self.parse_block()?;
Ok(IterationStatement {
span: start_span + block.span.clone(),
span: start_span + block.span,
variable: ident,
type_: type_.0,
start,
@ -171,7 +168,7 @@ impl ParserContext<'_> {
string = Some(match token {
Token::StringLit(chars) => chars,
_ => {
p.emit_err(ParserError::unexpected_str(token, "formatted string", &span));
p.emit_err(ParserError::unexpected_str(token, "formatted string", span));
Vec::new()
}
});
@ -207,7 +204,7 @@ impl ParserContext<'_> {
self.emit_err(ParserError::unexpected_ident(
x,
&["assert", "error", "log"],
&function.span,
function.span,
));
ConsoleFunction::Log(self.parse_console_args()?)
}
@ -215,21 +212,21 @@ impl ParserContext<'_> {
self.expect(&Token::Semicolon)?;
Ok(ConsoleStatement {
span: &keyword + function.span(),
span: keyword + function.span(),
function,
})
}
/// Returns a [`VariableName`] AST node if the next tokens represent a variable name with
/// valid keywords.
pub fn parse_variable_name(&mut self, decl_ty: Declare, span: &Span) -> Result<VariableName> {
pub fn parse_variable_name(&mut self, decl_ty: Declare, span: Span) -> Result<VariableName> {
if self.eat(&Token::Mut) {
self.emit_err(ParserError::let_mut_statement(&(&self.prev_token.span + span)));
self.emit_err(ParserError::let_mut_statement(self.prev_token.span + span));
}
let name = self.expect_ident()?;
Ok(VariableName {
span: name.span.clone(),
span: name.span,
mutable: matches!(decl_ty, Declare::Let),
identifier: name,
})
@ -238,7 +235,7 @@ impl ParserContext<'_> {
/// Returns a [`DefinitionStatement`] AST node if the next tokens represent a definition statement.
pub fn parse_definition_statement(&mut self) -> Result<DefinitionStatement> {
self.expect_any(&[Token::Let, Token::Const])?;
let decl_span = self.prev_token.span.clone();
let decl_span = self.prev_token.span;
let decl_type = match &self.prev_token.token {
Token::Let => Declare::Let,
Token::Const => Declare::Const,
@ -247,7 +244,7 @@ impl ParserContext<'_> {
// Parse variable names.
let variable_names = if self.peek_is_left_par() {
let vars = self
.parse_paren_comma_list(|p| p.parse_variable_name(decl_type, &decl_span).map(Some))
.parse_paren_comma_list(|p| p.parse_variable_name(decl_type, decl_span).map(Some))
.map(|(vars, ..)| vars)?;
if vars.len() == 1 {
@ -256,7 +253,7 @@ impl ParserContext<'_> {
vars
} else {
vec![self.parse_variable_name(decl_type, &decl_span)?]
vec![self.parse_variable_name(decl_type, decl_span)?]
};
self.expect(&Token::Colon)?;
@ -267,7 +264,7 @@ impl ParserContext<'_> {
self.expect(&Token::Semicolon)?;
Ok(DefinitionStatement {
span: &decl_span + expr.span(),
span: decl_span + expr.span(),
declaration_type: decl_type,
variable_names,
type_: type_.0,

View File

@ -17,7 +17,11 @@
use crate::{tokenizer, ParserContext, SpannedToken};
use leo_ast::{Expression, ExpressionStatement, Statement, ValueExpression};
use leo_errors::{emitter::Handler, LeoError};
use leo_span::{symbol::create_session_if_not_set_then, Span};
use leo_span::{
source_map::FileName,
symbol::{create_session_if_not_set_then, SessionGlobals},
Span,
};
use leo_test_framework::{
runner::{Namespace, ParseType, Runner},
Test,
@ -34,18 +38,16 @@ impl Namespace for TokenNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| {
tokenizer::tokenize("test", &test.content)
.map(|tokens| {
Value::String(
tokens
.into_iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(","),
)
})
.map_err(|x| x.to_string())
create_session_if_not_set_then(|s| {
tokenize(test, s).map(|tokens| {
Value::String(
tokens
.into_iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(","),
)
})
})
}
}
@ -76,8 +78,9 @@ fn with_handler<T>(
Ok(parsed)
}
fn tokenize(test: Test) -> Result<Vec<SpannedToken>, String> {
tokenizer::tokenize("test", &test.content).map_err(|x| x.to_string())
fn tokenize(test: Test, s: &SessionGlobals) -> Result<Vec<SpannedToken>, String> {
let sf = s.source_map.new_source(&test.content, FileName::Custom("test".into()));
tokenizer::tokenize(&sf.src, sf.start_pos).map_err(|x| x.to_string())
}
fn all_are_comments(tokens: &[SpannedToken]) -> bool {
@ -98,8 +101,8 @@ impl Namespace for ParseExpressionNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
create_session_if_not_set_then(|s| {
let tokenizer = tokenize(test, s)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(""));
}
@ -116,8 +119,8 @@ impl Namespace for ParseStatementNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
create_session_if_not_set_then(|s| {
let tokenizer = tokenize(test, s)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(Statement::Expression(ExpressionStatement {
expression: Expression::Value(ValueExpression::String(Vec::new(), Default::default())),
@ -137,7 +140,7 @@ impl Namespace for ParseNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| with_handler(tokenize(test)?, |p| p.parse_program()).map(yaml_or_fail))
create_session_if_not_set_then(|s| with_handler(tokenize(test, s)?, |p| p.parse_program()).map(yaml_or_fail))
}
}
@ -193,8 +196,8 @@ impl Namespace for SerializeNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
create_session_if_not_set_then(|s| {
let tokenizer = tokenize(test, s)?;
let parsed = with_handler(tokenizer, |p| p.parse_program())?;
let mut json = serde_json::to_value(parsed).expect("failed to convert to json value");
@ -214,7 +217,7 @@ impl Namespace for InputNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| with_handler(tokenize(test)?, |p| p.parse_input()).map(yaml_or_fail))
create_session_if_not_set_then(|s| with_handler(tokenize(test, s)?, |p| p.parse_input()).map(yaml_or_fail))
}
}

View File

@ -79,7 +79,6 @@ impl Token {
if let Ok(hex) = u32::from_str_radix(&unicode, 16) {
if let Some(character) = std::char::from_u32(hex) {
// scalar
Ok((len, Char::Scalar(character)))
} else if hex <= 0x10FFFF {
Ok((len, Char::NonScalar(hex)))
@ -451,7 +450,7 @@ pub struct SpannedToken {
impl SpannedToken {
/// Returns a dummy token at a dummy span.
pub fn dummy() -> Self {
pub const fn dummy() -> Self {
Self {
token: Token::Question,
span: Span::dummy(),

View File

@ -21,7 +21,6 @@
pub(crate) mod token;
use std::iter;
use std::sync::Arc;
pub use self::token::KEYWORD_TOKENS;
pub(crate) use self::token::*;
@ -30,78 +29,38 @@ pub(crate) mod lexer;
pub(crate) use self::lexer::*;
use leo_errors::{ParserError, Result};
use leo_span::Span;
use leo_span::{
span::{BytePos, Pos},
Span,
};
/// Creates a new vector of spanned tokens from a given file path and source code text.
pub(crate) fn tokenize(path: &str, input: &str) -> Result<Vec<SpannedToken>> {
tokenize_iter(path, input).collect()
pub(crate) fn tokenize(input: &str, start_pos: BytePos) -> Result<Vec<SpannedToken>> {
tokenize_iter(input, start_pos).collect()
}
/// Yields spanned tokens from a given file path and source code text.
pub(crate) fn tokenize_iter<'a>(path: &'a str, input: &'a str) -> impl 'a + Iterator<Item = Result<SpannedToken>> {
let path = Arc::new(path.to_string());
/// Yields spanned tokens from the given source code text.
///
/// The `lo` byte position determines where spans will start.
pub(crate) fn tokenize_iter(input: &str, mut lo: BytePos) -> impl '_ + Iterator<Item = Result<SpannedToken>> {
let mut index = 0usize;
let mut line_no = 1usize;
let mut line_start = 0usize;
iter::from_fn(move || {
while input.len() > index {
let token = match Token::eat(&input[index..]) {
let (token_len, token) = match Token::eat(&input[index..]) {
Err(e) => return Some(Err(e)),
Ok(t) => t,
};
index += token_len;
let span = Span::new(lo, lo + BytePos::from_usize(token_len));
lo = span.hi;
match token {
(token_len, Token::WhiteSpace) => {
let bytes = input.as_bytes();
if bytes[index] == 0x000D && matches!(bytes.get(index + 1), Some(0x000A)) {
// Check carriage return followed by newline.
line_no += 1;
line_start = index + token_len + 1;
index += token_len;
} else if matches!(bytes[index], 0x000A | 0x000D) {
// Check new-line or carriage-return
line_no += 1;
line_start = index + token_len;
}
index += token_len;
}
(token_len, token) => {
let mut span = Span::new(
line_no,
line_no,
index - line_start + 1,
index - line_start + token_len + 1,
path.clone(),
input[line_start
..input[line_start..]
.find('\n')
.map(|i| i + line_start)
.unwrap_or(input.len())]
.to_string(),
);
match &token {
Token::CommentLine(_) => {
line_no += 1;
line_start = index + token_len;
}
Token::CommentBlock(block) => {
let line_ct = block.chars().filter(|x| *x == '\n').count();
line_no += line_ct;
if line_ct > 0 {
let last_line_index = block.rfind('\n').unwrap();
line_start = index + last_line_index + 1;
span.col_stop = index + token_len - line_start + 1;
}
span.line_stop = line_no;
}
Token::AddressLit(address) if !check_address(address) => {
return Some(Err(ParserError::invalid_address_lit(address, &span).into()));
}
_ => (),
}
index += token_len;
return Some(Ok(SpannedToken { token, span }));
Token::WhiteSpace => continue,
Token::AddressLit(address) if !check_address(&address) => {
return Some(Err(ParserError::invalid_address_lit(address, span).into()));
}
_ => return Some(Ok(SpannedToken { token, span })),
}
}
@ -112,92 +71,90 @@ pub(crate) fn tokenize_iter<'a>(path: &'a str, input: &'a str) -> impl 'a + Iter
#[cfg(test)]
mod tests {
use super::*;
use leo_span::symbol::create_session_if_not_set_then;
use leo_span::{source_map::FileName, symbol::create_session_if_not_set_then};
#[test]
fn test_tokenizer() {
create_session_if_not_set_then(|_| {
let tokens = tokenize(
"test_path",
r#"
'a'
'😭'
"test"
"test{}test"
"test{}"
"{}test"
"test{"
"test}"
"test{test"
"test}test"
"te{{}}"
aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8
test_ident
12345
address
bool
const
else
false
field
for
function
group
i128
i64
i32
i16
i8
if
in
input
let
mut
return
scalar
string
test
true
u128
u64
u32
u16
u8
console
!
!=
&&
(
)
*
**
+
,
-
->
_
.
..
/
:
;
<
<=
=
==
>
>=
[
]
{{
}}
||
?
// test
/* test */
//"#,
)
.unwrap();
create_session_if_not_set_then(|s| {
let raw = r#"
'a'
'😭'
"test"
"test{}test"
"test{}"
"{}test"
"test{"
"test}"
"test{test"
"test}test"
"te{{}}"
aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8
test_ident
12345
address
bool
const
else
false
field
for
function
group
i128
i64
i32
i16
i8
if
in
input
let
mut
return
scalar
string
test
true
u128
u64
u32
u16
u8
console
!
!=
&&
(
)
*
**
+
,
-
->
_
.
..
/
:
;
<
<=
=
==
>
>=
[
]
{{
}}
||
?
// test
/* test */
//"#;
let sf = s.source_map.new_source(raw, FileName::Custom("test".into()));
let tokens = tokenize(&sf.src, sf.start_pos).unwrap();
let mut output = String::new();
for SpannedToken { token, .. } in tokens.iter() {
output += &format!("{} ", token);
@ -213,7 +170,7 @@ mod tests {
#[test]
fn test_spans() {
create_session_if_not_set_then(|_| {
create_session_if_not_set_then(|s| {
let raw = r#"
ppp test
// test
@ -224,7 +181,10 @@ ppp test
test */
test
"#;
let tokens = tokenize("test_path", raw).unwrap();
let sm = &s.source_map;
let sf = sm.new_source(raw, FileName::Custom("test".into()));
let tokens = tokenize(&sf.src, sf.start_pos).unwrap();
let mut line_indicies = vec![0];
for (i, c) in raw.chars().enumerate() {
if c == '\n' {
@ -232,11 +192,7 @@ ppp test
}
}
for token in tokens.iter() {
let token_raw = token.token.to_string();
let start = line_indicies.get(token.span.line_start - 1).unwrap();
let stop = line_indicies.get(token.span.line_stop - 1).unwrap();
let original = &raw[*start + token.span.col_start - 1..*stop + token.span.col_stop - 1];
assert_eq!(original, &token_raw);
assert_eq!(token.token.to_string(), sm.contents_of_span(token.span).unwrap());
}
})
}

View File

@ -37,7 +37,7 @@ pub struct SymbolTable<'a> {
impl<'a> SymbolTable<'a> {
pub fn check_shadowing(&self, symbol: &Symbol) -> Result<()> {
if let Some(function) = self.functions.get(symbol) {
Err(AstError::shadowed_function(symbol, &function.span).into())
Err(AstError::shadowed_function(symbol, function.span).into())
} else {
self.variables.check_shadowing(symbol)?;
Ok(())

View File

@ -41,7 +41,7 @@ impl Display for Declaration {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VariableSymbol<'a> {
pub type_: &'a Type,
pub span: &'a Span,
pub span: Span,
pub declaration: Declaration,
}

View File

@ -39,7 +39,7 @@ fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: Option<Ty
}
impl<'a> TypeChecker<'a> {
pub(crate) fn compare_expr_type(&mut self, expr: &Expression, expected: Option<Type>, span: &Span) -> Option<Type> {
pub(crate) fn compare_expr_type(&mut self, expr: &Expression, expected: Option<Type>, span: Span) -> Option<Type> {
match expr {
Expression::Identifier(ident) => {
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
@ -176,7 +176,8 @@ impl<'a> TypeChecker<'a> {
// Allow `group` * `scalar` multiplication.
match (t1.as_ref(), t2.as_ref()) {
(Some(Type::Group), Some(Type::Scalar)) | (Some(Type::Scalar), Some(Type::Group)) => {
(Some(Type::Group), Some(other)) | (Some(other), Some(Type::Group)) => {
self.assert_type(other.clone(), Some(Type::Scalar), binary.span());
Some(Type::Group)
}
_ => return_incorrect_type(t1, t2, expected),

View File

@ -73,7 +73,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
Some(var.type_.clone())
} else {
self.handler.emit_err(
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, &input.assignee.span).into(),
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, input.assignee.span).into(),
);
None

View File

@ -96,7 +96,7 @@ impl<'a> TypeChecker<'a> {
}
}
pub(crate) fn assert_type(&self, type_: Type, expected: Option<Type>, span: &Span) -> Type {
pub(crate) fn assert_type(&self, type_: Type, expected: Option<Type>, span: Span) -> Type {
if let Some(expected) = expected {
if type_ != expected {
self.handler
@ -107,7 +107,7 @@ impl<'a> TypeChecker<'a> {
type_
}
pub(crate) fn assert_one_of_types(&self, type_: Option<Type>, expected: &[Type], span: &Span) -> Option<Type> {
pub(crate) fn assert_one_of_types(&self, type_: Option<Type>, expected: &[Type], span: Span) -> Option<Type> {
if let Some(type_) = type_.clone() {
for t in expected.iter() {
if &type_ == t {
@ -128,19 +128,19 @@ impl<'a> TypeChecker<'a> {
type_
}
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: Option<Type>, span: &Span) -> Option<Type> {
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, FIELD_GROUP_SCALAR_INT, span)
}
pub(crate) fn assert_field_group_int_type(&self, type_: Option<Type>, span: &Span) -> Option<Type> {
pub(crate) fn assert_field_group_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, FIELD_GROUP_INT, span)
}
pub(crate) fn assert_field_int_type(&self, type_: Option<Type>, span: &Span) -> Option<Type> {
pub(crate) fn assert_field_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, FIELD_INT_TYPES, span)
}
pub(crate) fn assert_int_type(&self, type_: Option<Type>, span: &Span) -> Option<Type> {
pub(crate) fn assert_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, INT_TYPES, span)
}
}

Binary file not shown.

View File

@ -222,9 +222,9 @@ address-type = %s"address"
character-type = %s"char"
scalar-type = boolean-type / arithmetic-type / address-type / character-type
primitive-type = boolean-type / arithmetic-type / address-type / character-type
type = scalar-type
type = primitive-type
group-coordinate = ( [ "-" ] numeral ) / "+" / "-" / "_"

View File

@ -20,6 +20,7 @@ use backtrace::Backtrace;
use color_backtrace::{BacktracePrinter, Verbosity};
use colored::Colorize;
use derivative::Derivative;
use leo_span::source_map::is_not_test_framework;
/// The indent for an error message.
pub(crate) const INDENT: &str = " ";
@ -120,12 +121,7 @@ impl fmt::Display for Backtraced {
let message = format!("{kind} [{code}]: {message}", message = self.message,);
// To avoid the color enabling characters for comparison with test expectations.
if std::env::var("LEO_TESTFRAMEWORK")
.unwrap_or_default()
.trim()
.to_owned()
.is_empty()
{
if is_not_test_framework() {
if self.error {
write!(f, "{}", message.bold().red())?;
} else {

View File

@ -16,7 +16,7 @@
use crate::{Backtraced, INDENT};
use leo_span::Span;
use leo_span::{source_map::SpanLocation, symbol::with_session_globals, Span};
use backtrace::Backtrace;
use color_backtrace::{BacktracePrinter, Verbosity};
@ -50,14 +50,14 @@ impl Formatted {
code_identifier: i8,
type_: String,
error: bool,
span: &Span,
span: Span,
backtrace: Backtrace,
) -> Self
where
S: ToString,
{
Self {
span: span.clone(),
span,
backtrace: Backtraced::new_from_backtrace(
message.to_string(),
help,
@ -107,7 +107,18 @@ impl fmt::Display for Formatted {
underline
};
let underlined = underline(self.span.col_start, self.span.col_stop);
let (loc, contents) = with_session_globals(|s| {
(
s.source_map
.span_to_location(self.span)
.unwrap_or_else(SpanLocation::dummy),
s.source_map
.line_contents_of_span(self.span)
.unwrap_or_else(|| "<contents unavailable>".to_owned()),
)
});
let underlined = underline(loc.col_start, loc.col_stop);
let (kind, code) = if self.backtrace.error {
("Error", self.error_code())
@ -138,17 +149,17 @@ impl fmt::Display for Formatted {
"\n{indent }--> {path}:{line_start}:{start}\n\
{indent } |\n",
indent = INDENT,
path = &*self.span.path,
line_start = self.span.line_start,
start = self.span.col_start,
path = &loc.source_file.name,
line_start = loc.line_start,
start = loc.col_start,
)?;
for (line_no, line) in self.span.content.lines().enumerate() {
for (line_no, line) in contents.lines().enumerate() {
writeln!(
f,
"{line_no:width$} | {text}",
width = INDENT.len(),
line_no = self.span.line_start + line_no,
line_no = loc.line_start + line_no,
text = line,
)?;
}

View File

@ -96,7 +96,7 @@ macro_rules! create_messages {
// Formatted errors always takes a span.
$(#[$error_func_docs])*
// Expands additional arguments for the error defining function.
pub fn $name($($arg_names: $arg_types,)* span: &leo_span::Span) -> Self {
pub fn $name($($arg_names: $arg_types,)* span: leo_span::Span) -> Self {
Self::Formatted(
Formatted::new_from_span(
$message,

View File

@ -265,7 +265,7 @@ impl Handler {
mod tests {
use super::*;
use crate::ParserError;
use leo_span::Span;
use leo_span::{symbol::create_session_if_not_set_then, Span};
#[test]
fn fresh_no_errors() {
@ -276,28 +276,30 @@ mod tests {
#[test]
fn buffer_works() {
let count_err = |s: String| s.lines().filter(|l| l.contains("Error")).count();
create_session_if_not_set_then(|_| {
let count_err = |s: String| s.lines().filter(|l| l.contains("Error")).count();
let res: Result<(), _> = Handler::with(|h| {
let s = Span::default();
assert_eq!(h.err_count(), 0);
h.emit_err(ParserError::invalid_import_list(&s).into());
assert_eq!(h.err_count(), 1);
h.emit_err(ParserError::unexpected_eof(&s).into());
assert_eq!(h.err_count(), 2);
Err(ParserError::spread_in_array_init(&s).into())
});
let res: Result<(), _> = Handler::with(|h| {
let s = Span::default();
assert_eq!(h.err_count(), 0);
h.emit_err(ParserError::invalid_import_list(s).into());
assert_eq!(h.err_count(), 1);
h.emit_err(ParserError::unexpected_eof(s).into());
assert_eq!(h.err_count(), 2);
Err(ParserError::spread_in_array_init(s).into())
});
assert_eq!(count_err(res.unwrap_err().to_string()), 3);
assert_eq!(count_err(res.unwrap_err().to_string()), 3);
let res: Result<(), _> = Handler::with(|h| {
let s = Span::default();
h.emit_err(ParserError::invalid_import_list(&s).into());
h.emit_err(ParserError::unexpected_eof(&s).into());
Ok(())
});
assert_eq!(count_err(res.unwrap_err().to_string()), 2);
let res: Result<(), _> = Handler::with(|h| {
let s = Span::default();
h.emit_err(ParserError::invalid_import_list(s).into());
h.emit_err(ParserError::unexpected_eof(s).into());
Ok(())
});
assert_eq!(count_err(res.unwrap_err().to_string()), 2);
let () = Handler::with(|_| Ok(())).unwrap();
let () = Handler::with(|_| Ok(())).unwrap();
})
}
}

View File

@ -180,27 +180,27 @@ fn set_panic_hook() {
#[cfg(not(debug_assertions))]
std::panic::set_hook({
Box::new(move |e| {
println!(
eprintln!(
"thread `{}` {}",
std::thread::current().name().unwrap_or("<unnamed>"),
e
);
println!("stack backtrace: \n{:?}", backtrace::Backtrace::new());
println!("error: internal compiler error: unexpected panic\n");
println!("note: the compiler unexpectedly panicked. this is a bug.\n");
println!("note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n");
println!(
eprintln!("stack backtrace: \n{:?}", backtrace::Backtrace::new());
eprintln!("error: internal compiler error: unexpected panic\n");
eprintln!("note: the compiler unexpectedly panicked. this is a bug.\n");
eprintln!("note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n");
eprintln!(
"note: {} {} running on {} {}\n",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
sys_info::os_type().unwrap_or_else(|e| e.to_string()),
sys_info::os_release().unwrap_or_else(|e| e.to_string()),
);
println!(
eprintln!(
"note: compiler args: {}\n",
std::env::args().collect::<Vec<_>>().join(" ")
);
println!("note: compiler flags: {:?}\n", Opt::from_args());
eprintln!("note: compiler flags: {:?}\n", Opt::from_args());
})
});
}

View File

@ -18,16 +18,8 @@ license = "GPL-3.0"
edition = "2021"
rust-version = "1.56.1"
[dependencies.fxhash]
version = "0.2.1"
[dependencies.indexmap]
version = "1.8"
features = ["serde"]
[dependencies.serde]
version = "1.0.133"
features = [ "derive", "rc" ]
[dependencies.scoped-tls]
version = "1.0.0"
[dependencies]
fxhash = "0.2.1"
indexmap = { version = "1.8", features = ["serde"] }
serde = { version = "1.0.133", features = [ "derive", "rc" ] }
scoped-tls = { version = "1.0.0" }

View File

@ -23,3 +23,5 @@ pub mod span;
pub use span::Span;
pub mod span_json;
pub mod source_map;

441
leo/span/src/source_map.rs Normal file
View File

@ -0,0 +1,441 @@
use crate::span::{BytePos, CharPos, Pos, Span};
use std::{
cell::RefCell,
fmt, fs, io,
path::{Path, PathBuf},
rc::Rc,
};
/// The source map containing all recorded sources,
/// methods to register new ones,
/// and methods to query about spans in relation to recorded sources.
#[derive(Default)]
pub struct SourceMap {
/// The actual source map data.
inner: RefCell<SourceMapInner>,
}
/// Actual data of the source map.
/// We use this setup for purposes of interior mutability.
#[derive(Default)]
struct SourceMapInner {
/// The address space below this value is currently used by the files in the source map.
used_address_space: u32,
/// All the source files recorded thus far.
///
/// The list is append-only with mappings from the start byte position
/// for fast lookup from a `Span` to its `SourceFile`.
source_files: Vec<Rc<SourceFile>>,
}
impl SourceMap {
/// Loads the given `path` and returns a `SourceFile` for it.
pub fn load_file(&self, path: &Path) -> io::Result<Rc<SourceFile>> {
Ok(self.new_source(&fs::read_to_string(path)?, FileName::Real(path.to_owned())))
}
/// Registers `source` under the given file `name`, returning a `SourceFile` back.
pub fn new_source(&self, source: &str, name: FileName) -> Rc<SourceFile> {
let len = u32::try_from(source.len()).unwrap();
let mut inner = self.inner.borrow_mut();
let start_pos = inner.try_allocate_address_space(len).unwrap();
let source_file = Rc::new(SourceFile::new(name, source.to_owned(), start_pos));
inner.source_files.push(source_file.clone());
source_file
}
/// Find the index for the source file containing `pos`.
fn find_source_file_index(&self, pos: BytePos) -> Option<usize> {
self.inner
.borrow()
.source_files
.binary_search_by_key(&pos, |file| file.start_pos)
.map_or_else(|p| p.checked_sub(1), Some)
}
/// Find the source file containing `pos`.
fn find_source_file(&self, pos: BytePos) -> Option<Rc<SourceFile>> {
Some(self.inner.borrow().source_files[self.find_source_file_index(pos)?].clone())
}
/// Finds line column info about a given `pos`.
fn find_line_col(&self, pos: BytePos) -> Option<LineCol> {
let source_file = self.find_source_file(pos)?;
let (line, col) = source_file.lookup_file_pos(pos);
Some(LineCol { source_file, line, col })
}
/// Retrives the location (source file, line, col) on the given span.
pub fn span_to_location(&self, sp: Span) -> Option<SpanLocation> {
let lo = self.find_line_col(sp.lo)?;
let hi = self.find_line_col(sp.hi)?;
Some(SpanLocation {
source_file: lo.source_file,
line_start: lo.line,
line_stop: hi.line,
col_start: lo.col.to_usize() + 1,
col_stop: hi.col.to_usize() + 1,
})
}
/// Returns a displayable representation of the `span` as a string.
pub fn span_to_string(&self, span: Span) -> String {
let loc = match self.span_to_location(span) {
None => return "no-location".to_string(),
Some(l) => l,
};
if loc.line_start == loc.line_stop {
format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_stop)
} else {
format!(
"{}:{}-{}:{}",
loc.line_start, loc.col_start, loc.line_stop, loc.col_stop
)
}
}
/// Returns the source contents that is spanned by `span`.
pub fn contents_of_span(&self, span: Span) -> Option<String> {
let begin = self.find_source_file(span.lo)?;
let end = self.find_source_file(span.hi)?;
assert_eq!(begin.start_pos, end.start_pos);
Some(begin.contents_of_span(span))
}
/// Returns the source contents of the lines that `span` is within.
///
/// That is, if the span refers to `x = 4` in the source code:
///
/// > ```text
/// > // Line 1
/// > let x
/// > = 4;
/// > // Line 4
/// > ```
///
/// then the contents on lines 2 and 3 are returned.
pub fn line_contents_of_span(&self, span: Span) -> Option<String> {
let begin = self.find_source_file(span.lo)?;
let end = self.find_source_file(span.hi)?;
assert_eq!(begin.start_pos, end.start_pos);
let idx_lo = begin.lookup_line(span.lo).unwrap_or(0);
let idx_hi = begin.lookup_line(span.hi).unwrap_or(0) + 1;
let lo_line_pos = begin.lines[idx_lo];
let hi_line_pos = if idx_hi < begin.lines.len() {
begin.lines[idx_hi]
} else {
begin.end_pos
};
Some(begin.contents_of_span(Span::new(lo_line_pos, hi_line_pos)))
}
}
impl SourceMapInner {
/// Attempt reserving address space for `size` number of bytes.
fn try_allocate_address_space(&mut self, size: u32) -> Option<BytePos> {
let current = self.used_address_space;
// By adding one, we can distinguish between files, even when they are empty.
self.used_address_space = current.checked_add(size)?.checked_add(1)?;
Some(BytePos(current))
}
}
/// A file name.
///
/// For now it's simply a wrapper around `PathBuf`,
/// but may become more complicated in the future.
#[derive(Clone)]
pub enum FileName {
/// A real file.
Real(PathBuf),
/// Any sort of description for a source.
Custom(String),
}
impl fmt::Display for FileName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Real(x) if is_not_test_framework() => x.display().fmt(f),
Self::Real(_) => Ok(()),
Self::Custom(x) => f.write_str(x),
}
}
}
/// Is the env var `LEO_TESTFRAMEWORK` not enabled?
pub fn is_not_test_framework() -> bool {
std::env::var("LEO_TESTFRAMEWORK")
.unwrap_or_default()
.trim()
.to_owned()
.is_empty()
}
/// A single source in the [`SourceMap`].
pub struct SourceFile {
/// The name of the file that the source came from.
pub name: FileName,
/// The complete source code.
pub src: String,
/// The start position of this source in the `SourceMap`.
pub start_pos: BytePos,
/// The end position of this source in the `SourceMap`.
pub end_pos: BytePos,
/// Locations of line beginnings in the source code.
lines: Vec<BytePos>,
/// Locations of multi-byte characters in the source code.
multibyte_chars: Vec<MultiByteChar>,
}
impl SourceFile {
/// Creates a new `SourceMap` given the file `name`,
/// source contents, and the `start_pos`ition.
///
/// This position is used for analysis purposes.
fn new(name: FileName, mut src: String, start_pos: BytePos) -> Self {
normalize_src(&mut src);
let end_pos = start_pos + BytePos::from_usize(src.len());
let (lines, multibyte_chars) = analyze_source_file(&src, start_pos);
Self {
name,
src,
start_pos,
end_pos,
lines,
multibyte_chars,
}
}
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
// The number of extra bytes due to multibyte chars in the `SourceFile`.
let mut total_extra_bytes = 0;
for mbc in self.multibyte_chars.iter() {
if mbc.pos < bpos {
// Every character is at least one byte, so we only
// count the actual extra bytes.
total_extra_bytes += mbc.bytes as u32 - 1;
// We should never see a byte position in the middle of a
// character.
assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
} else {
break;
}
}
assert!(self.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32());
CharPos(bpos.to_usize() - self.start_pos.to_usize() - total_extra_bytes as usize)
}
/// Finds the line containing the given position. The return value is the
/// index into the `lines` array of this `SourceFile`, not the 1-based line
/// number. If the source_file is empty or the position is located before the
/// first line, `None` is returned.
fn lookup_line(&self, pos: BytePos) -> Option<usize> {
match self.lines.binary_search(&pos) {
Ok(idx) => Some(idx),
Err(0) => None,
Err(idx) => Some(idx - 1),
}
}
/// Looks up the file's (1-based) line number and (0-based `CharPos`) column offset, for a
/// given `BytePos`.
fn lookup_file_pos(&self, pos: BytePos) -> (usize, CharPos) {
let chpos = self.bytepos_to_file_charpos(pos);
match self.lookup_line(pos) {
Some(a) => {
let line = a + 1; // Line numbers start at 1
let linebpos = self.lines[a];
let linechpos = self.bytepos_to_file_charpos(linebpos);
let col = chpos - linechpos;
assert!(chpos >= linechpos);
(line, col)
}
None => (0, chpos),
}
}
/// Returns contents of a `span` assumed to be within the given file.
fn contents_of_span(&self, span: Span) -> String {
let begin_pos = self.bytepos_to_file_charpos(span.lo).to_usize();
let end_pos = self.bytepos_to_file_charpos(span.hi).to_usize();
String::from_utf8_lossy(&self.src.as_bytes()[begin_pos..end_pos]).into_owned()
}
}
/// Detailed information on a `Span`.
pub struct SpanLocation {
pub source_file: Rc<SourceFile>,
pub line_start: usize,
pub line_stop: usize,
pub col_start: usize,
pub col_stop: usize,
}
impl SpanLocation {
/// Returns a dummy location.
pub fn dummy() -> Self {
let dummy = "<dummy>".to_owned();
let span = Span::dummy();
Self {
source_file: Rc::new(SourceFile {
name: FileName::Custom(dummy.clone()),
src: dummy,
start_pos: span.lo,
end_pos: span.hi,
lines: Vec::new(),
multibyte_chars: Vec::new(),
}),
line_start: 0,
line_stop: 0,
col_start: 0,
col_stop: 0,
}
}
}
/// File / Line / Column information on a `BytePos`.
pub struct LineCol {
/// Information on the original source.
pub source_file: Rc<SourceFile>,
/// The 1-based line number.
pub line: usize,
/// The (0-based) column offset into the line.
pub col: CharPos,
}
/// Normalizes the source code and records the normalizations.
fn normalize_src(src: &mut String) {
remove_bom(src);
normalize_newlines(src);
}
/// Removes UTF-8 BOM, if any.
fn remove_bom(src: &mut String) {
if src.starts_with('\u{feff}') {
src.drain(..3);
}
}
/// Replaces `\r\n` with `\n` in-place in `src`.
///
/// Returns error if there's a lone `\r` in the string.
fn normalize_newlines(src: &mut String) {
if !src.as_bytes().contains(&b'\r') {
return;
}
// We replace `\r\n` with `\n` in-place, which doesn't break utf-8 encoding.
// While we *can* call `as_mut_vec` and do surgery on the live string
// directly, let's rather steal the contents of `src`. This makes the code
// safe even if a panic occurs.
let mut buf = std::mem::take(src).into_bytes();
let mut gap_len = 0;
let mut tail = buf.as_mut_slice();
loop {
let idx = match find_crlf(&tail[gap_len..]) {
None => tail.len(),
Some(idx) => idx + gap_len,
};
tail.copy_within(gap_len..idx, 0);
tail = &mut tail[idx - gap_len..];
if tail.len() == gap_len {
break;
}
gap_len += 1;
}
// Account for removed `\r`.
// After `set_len`, `buf` is guaranteed to contain utf-8 again.
let new_len = buf.len() - gap_len;
unsafe {
buf.set_len(new_len);
*src = String::from_utf8_unchecked(buf);
}
fn find_crlf(src: &[u8]) -> Option<usize> {
let mut search_idx = 0;
while let Some(idx) = find_cr(&src[search_idx..]) {
if src[search_idx..].get(idx + 1) != Some(&b'\n') {
search_idx += idx + 1;
continue;
}
return Some(search_idx + idx);
}
None
}
fn find_cr(src: &[u8]) -> Option<usize> {
src.iter().position(|&b| b == b'\r')
}
}
/// Identifies an offset of a multi-byte character in a `SourceFile`.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct MultiByteChar {
/// The absolute offset of the character in the `SourceMap`.
pub pos: BytePos,
/// The number of bytes, `>= 2`.
pub bytes: u8,
}
/// Finds all newlines, multi-byte characters, and non-narrow characters in a
/// SourceFile.
///
/// This function will use an SSE2 enhanced implementation if hardware support
/// is detected at runtime.
fn analyze_source_file(src: &str, source_file_start_pos: BytePos) -> (Vec<BytePos>, Vec<MultiByteChar>) {
let mut lines = vec![source_file_start_pos];
let mut multi_byte_chars = vec![];
let mut i = 0;
let src_bytes = src.as_bytes();
while i < src.len() {
// SAFETY: We verified that i < src.len().
let i_usize = i as usize;
let byte = unsafe { *src_bytes.get_unchecked(i_usize) };
// How much to advance to get to the next UTF-8 char in the string.
let mut char_len = 1;
let pos = BytePos::from_usize(i) + source_file_start_pos;
if let b'\n' = byte {
lines.push(pos + BytePos(1));
} else if byte >= 127 {
// The slow path:
// This is either ASCII control character "DEL" or the beginning of
// a multibyte char. Just decode to `char`.
let c = (&src[i..]).chars().next().unwrap();
char_len = c.len_utf8();
if char_len > 1 {
assert!((2..=4).contains(&char_len));
let bytes = char_len as u8;
let mbc = MultiByteChar { pos, bytes };
multi_byte_chars.push(mbc);
}
}
i += char_len;
}
// The code above optimistically registers a new line *after* each \n it encounters.
// If that point is already outside the source_file, remove it again.
if let Some(&last_line_start) = lines.last() {
let source_file_end = source_file_start_pos + BytePos::from_usize(src.len());
assert!(source_file_end >= last_line_start);
if last_line_start == source_file_end {
lines.pop();
}
}
(lines, multi_byte_chars)
}

View File

@ -16,103 +16,47 @@
//! Defines the `Span` type used to track where code comes from.
use std::{fmt, sync::Arc, usize};
use core::ops::{Add, Sub};
use serde::{Deserialize, Serialize};
use std::{fmt, usize};
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde::Deserialize;
use crate::symbol::with_session_globals;
/// The span type which tracks where formatted errors originate from in a Leo file.
/// This is used in many spots throughout the rest of the Leo crates.
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq)]
#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Span {
// TODO(Centril): All of could be optimized to just `{ lo: u32, hi: u32 }`,
// i.e. 8 bytes by indexing into a global source map of all files concatenated.
// That would also give us `Copy` which is quite nice!
/// The line number where the error started.
pub line_start: usize,
/// The line number where the error stopped.
pub line_stop: usize,
/// The column number where the error started.
pub col_start: usize,
/// The column number where the error stopped.
pub col_stop: usize,
/// The path to the Leo file containing the error.
pub path: Arc<String>,
/// The content of the line(s) that the span is found on.
pub content: String,
/// The start position of the span.
pub lo: BytePos,
/// The end position of the span.
/// The length is simply `end - start`.
pub hi: BytePos,
}
impl Span {
/// Generate a new span from:
/// - Where the Leo line starts.
/// - Where the Leo line stops.
/// - Where the Leo column starts.
/// - Where the Leo column stops.
/// - The path to the Leo file.
/// - The content of those specified bounds.
pub fn new(
line_start: usize,
line_stop: usize,
col_start: usize,
col_stop: usize,
path: Arc<String>,
content: String,
) -> Self {
Self {
line_start,
line_stop,
col_start,
col_stop,
path,
content,
}
/// Generate a new span from the `start`ing and `end`ing positions.
pub fn new(start: BytePos, end: BytePos) -> Self {
Self { lo: start, hi: end }
}
/// Generates a dummy span with all defaults.
/// Should only be used in temporary situations.
pub fn dummy() -> Self {
Self::new(0, 0, 0, 0, <_>::default(), <_>::default())
}
}
impl Serialize for Span {
/// Custom serialization for testing purposes.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Color", 3)?;
state.serialize_field("line_start", &self.line_start)?;
state.serialize_field("line_stop", &self.line_stop)?;
state.serialize_field("col_start", &self.col_start)?;
state.serialize_field("col_stop", &self.col_stop)?;
// This is for testing purposes since the tests are run on a variety of OSes.
if std::env::var("LEO_TESTFRAMEWORK")
.unwrap_or_default()
.trim()
.to_owned()
.is_empty()
{
state.serialize_field("path", &self.path)?;
} else {
state.serialize_field("path", "")?;
pub const fn dummy() -> Self {
Self {
lo: BytePos(0),
hi: BytePos(0),
}
state.serialize_field("content", &self.content)?;
state.end()
}
/// Is the span a dummy?
pub fn is_dummy(&self) -> bool {
self == &Self::dummy()
}
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.line_start == self.line_stop {
write!(f, "{}:{}-{}", self.line_start, self.col_start, self.col_stop)
} else {
write!(
f,
"{}:{}-{}:{}",
self.line_start, self.col_start, self.line_stop, self.col_stop
)
}
with_session_globals(|s| write!(f, "{}", s.source_map.span_to_string(*self)))
}
}
@ -120,69 +64,95 @@ impl std::ops::Add for &Span {
type Output = Span;
fn add(self, other: &Span) -> Span {
self.clone() + other.clone()
*self + *other
}
}
impl std::ops::Add for Span {
type Output = Self;
#[allow(clippy::comparison_chain)]
fn add(self, other: Self) -> Self {
if self.line_start == other.line_stop {
Span {
line_start: self.line_start,
line_stop: self.line_stop,
col_start: self.col_start.min(other.col_start),
col_stop: self.col_stop.max(other.col_stop),
path: self.path,
content: self.content,
}
} else {
let mut new_content = vec![];
let self_lines = self.content.lines().collect::<Vec<_>>();
let other_lines = other.content.lines().collect::<Vec<_>>();
for line in self.line_start.min(other.line_start)..self.line_stop.max(other.line_stop) + 1 {
if line >= self.line_start && line <= self.line_stop {
new_content.push(
self_lines
.get(line - self.line_start)
.copied()
.unwrap_or_default()
.to_string(),
);
} else if line >= other.line_start && line <= other.line_stop {
new_content.push(
other_lines
.get(line - other.line_start)
.copied()
.unwrap_or_default()
.to_string(),
);
} else if new_content.last().map(|x| *x != "...").unwrap_or(true) {
new_content.push(format!("{:<1$}...", " ", other.col_start + 4));
}
}
let new_content = new_content.join("\n");
if self.line_start < other.line_stop {
Span {
line_start: self.line_start,
line_stop: other.line_stop,
col_start: self.col_start,
col_stop: other.col_stop,
path: self.path,
content: new_content,
}
} else {
Span {
line_start: other.line_start,
line_stop: self.line_stop,
col_start: other.col_start,
col_stop: self.col_stop,
path: self.path,
content: new_content,
}
}
}
let lo = self.lo.min(other.lo);
let hi = self.hi.max(other.hi);
Self::new(lo, hi)
}
}
// _____________________________________________________________________________
// Pos, BytePos, CharPos
//
pub trait Pos {
fn from_usize(n: usize) -> Self;
fn to_usize(&self) -> usize;
fn from_u32(n: u32) -> Self;
fn to_u32(&self) -> u32;
}
macro_rules! impl_pos {
(
$(
$(#[$attr:meta])*
$vis:vis struct $ident:ident($inner_vis:vis $inner_ty:ty);
)*
) => {
$(
$(#[$attr])*
$vis struct $ident($inner_vis $inner_ty);
impl Pos for $ident {
#[inline(always)]
fn from_usize(n: usize) -> $ident {
$ident(n as $inner_ty)
}
#[inline(always)]
fn to_usize(&self) -> usize {
self.0 as usize
}
#[inline(always)]
fn from_u32(n: u32) -> $ident {
$ident(n as $inner_ty)
}
#[inline(always)]
fn to_u32(&self) -> u32 {
self.0 as u32
}
}
impl Add for $ident {
type Output = $ident;
#[inline(always)]
fn add(self, rhs: $ident) -> $ident {
$ident(self.0 + rhs.0)
}
}
impl Sub for $ident {
type Output = $ident;
#[inline(always)]
fn sub(self, rhs: $ident) -> $ident {
$ident(self.0 - rhs.0)
}
}
)*
};
}
impl_pos! {
/// A byte offset.
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize, Default)]
pub struct BytePos(pub u32);
/// A character offset.
///
/// Because of multibyte UTF-8 characters,
/// a byte offset is not equivalent to a character offset.
/// The [`SourceMap`] will convert [`BytePos`] values to `CharPos` values as necessary.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CharPos(pub usize);
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::dropless::DroplessArena;
use crate::source_map::SourceMap;
use core::cmp::PartialEq;
use core::convert::AsRef;
@ -288,12 +289,15 @@ impl fmt::Display for SymbolStr {
pub struct SessionGlobals {
/// The interner for `Symbol`s used in the compiler.
symbol_interner: Interner,
/// The source map used in the compiler.
pub source_map: SourceMap,
}
impl SessionGlobals {
fn new() -> Self {
Self {
symbol_interner: Interner::prefilled(),
source_map: SourceMap::default(),
}
}
}

View File

@ -5,5 +5,5 @@ input_file: inputs/one.in
*/
function main(a: group) -> group {
return 1u8 * a;
return 1scalar * a;
}

View File

@ -1,3 +1,10 @@
function main(element: group) {
const b = element;
}
/*
namespace: Compile
expectation: Pass
*/
function main() -> group {
const element: group = (0, 1)group;
return element;
}

View File

@ -0,0 +1,7 @@
[main]
a: i128 = 2i128;
b: i128 = 2i128;
c: i128 = 4i128;
[registers]
r0: bool = true;

View File

@ -1,3 +1,9 @@
/*
namespace: Compile
expectation: Fail
input_file: inputs/pow.in
*/
function main(a: i128, b: i128, c: i128) -> bool {
return a ** b == c;
}

View File

@ -0,0 +1,7 @@
[main]
a: i32 = 2i32;
b: i32 = 2i32;
c: i32 = 4i32;
[registers]
r0: bool = true;

View File

@ -1,3 +1,9 @@
/*
namespace: Compile
expectation: Fail
input_file: inputs/pow.in
*/
function main(a: i32, b: i32, c: i32) -> bool {
return a ** b == c;
}

View File

@ -0,0 +1,7 @@
[main]
a: i64 = 2i64;
b: i64 = 2i64;
c: i64 = 4i64;
[registers]
r0: bool = true;

View File

@ -1,3 +0,0 @@
function main(a: i64, b: i64) -> bool {
return a ** 4 == b;
}

View File

@ -0,0 +1,9 @@
/*
namespace: Compile
expectation: Fail
input_file: inputs/pow.in
*/
function main(a: i64, b: i64, c: i64) -> bool {
return a ** b == c;
}

View File

@ -0,0 +1,7 @@
[main]
a: u128 = 2u128;
b: u128 = 2u128;
c: u128 = 4u128;
[registers]
r0: bool = true;

View File

@ -1,3 +1,12 @@
/*
namespace: Compile
expectation: Pass
input_file: inputs/pow.in
# This test might take to long to fully compile.
# If necessary we could move it to disabled_tests.
*/
function main(a: u128, b: u128, c: u128) -> bool {
return a ** b == c;
}

View File

@ -0,0 +1,7 @@
[main]
a: u32 = 2u32;
b: u32 = 2u32;
c: u32 = 4u32;
[registers]
r0: bool = true;

View File

@ -1,3 +1,12 @@
/*
namespace: Compile
expectation: Pass
input_file: inputs/pow.in
# This test might take to long to fully compile.
# If necessary we could move it to disabled_tests.
*/
function main(a: u32, b: u32, c: u32) -> bool {
return a ** b == c;
}

View File

@ -0,0 +1,7 @@
[main]
a: u64 = 2u64;
b: u64 = 2u64;
c: u64 = 4u64;
[registers]
r0: bool = true;

View File

@ -1,3 +1,12 @@
/*
namespace: Compile
expectation: Pass
input_file: inputs/pow.in
# This test might take to long to fully compile.
# If necessary we could move it to disabled_tests.
*/
function main(a: u64, b: u64, c: u64) -> bool {
return a ** b == c;
}

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: bbe973798ab14152165455260924a0de60131d31da32d2e223228954365dc609
initial_ast: fa5f2ab70ae04bbd7684fc630de6cd5d6d85e791ccf9f06e65b7ae6a03e2ec48
- initial_input_ast: c7315faf1ac3ceeb90260e64e4a411a27a8aa732892a64c15f49e81adf464beb
initial_ast: b80eed2960509f11bce6294687558fb7b907f1d83455287f944dfa981ebe1ec8
symbol_table: 9d42b1d8f167826635e5169bc3a50c14f722fba8e5ce2480fbde3b8cf2e75237

View File

@ -3,7 +3,7 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 98da6a76f2370e9311042851dde02ebaa4e64528d9461a5e722858f394d25f93
- initial_input_ast: 85307a4f16278d38b746d321756e41c3cf48bbb2dc5bad2f0e9a7b8c4dd2541e
initial_ast: 998b6e02af1be3c649cecd0129810b237f33289b801d24a90c38260561cc0318
- initial_input_ast: dc6b4b00185dd6c1f2b83a1bfae619c1d6e3f68ac0f1d3d87ae3bd0ed5caf083
- initial_input_ast: 73a38568160c3d2be402043d04ccdc2290abe27647bc81c4bd50367834c206cf
initial_ast: 6514080a9452d6e193510250dec3b87081e0741d05cc59ca456f2b2f3f36ec72
symbol_table: 7ec407fabcae0eeef889009b8ba99beac3d18b2d79cc49e7760261d80bd59728

View File

@ -3,7 +3,7 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 98da6a76f2370e9311042851dde02ebaa4e64528d9461a5e722858f394d25f93
- initial_input_ast: 85307a4f16278d38b746d321756e41c3cf48bbb2dc5bad2f0e9a7b8c4dd2541e
initial_ast: c1865cfe898ea72b3f411b63364f3643ad452860c6d1db92e843f2c61094eec9
- initial_input_ast: b6371958e735320861c84ed514f258ae8a9858b34615364b2f9ebbaa2aaadd8c
- initial_input_ast: d384cfea1a36220e9ea4e246ece89d8fffa320f90aeeb85660bc445ab62a0829
initial_ast: 7085f8bf0a01a4fd7b73b5e3fc1c2c812d0cd459a5b6ea85791fc3c01118c7a0
symbol_table: 5a12f141aef86a7a00b86650e23cfd9af657d6f418df7b1ee9eab06714305d31

View File

@ -3,9 +3,9 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 51b03881ad0ef3af7d105c163071fb69fb38048bea44c4bc380fd17367ce94e0
- initial_input_ast: 59b58754cc7667404c6bba5d90a9e53b7f9f36b6d7c9783e5b88d12728127e66
- initial_input_ast: 55ff7a9a3f210ea871c438a89f07da6c54ca1b8129e7344593017d22305297b4
- initial_input_ast: c89564770d1984e4e8c0c17c6c50b66b4a5d4ade85899562f506afc22e50496d
initial_ast: 30050aaa080b73f03ccc9a5fda9bdb9fcba0aea90171b8cdf39c50c5eb8ac7ab
- initial_input_ast: e6457724e4c3bb27eca30df861f711f962ac47fb0e7d0b9dc959be0feaeb7763
- initial_input_ast: c8d27a86795a6d56815a681066b7f462f5476be6d56ec910b74d90c60d8b3cc9
- initial_input_ast: 4ff2fb01e2d10a59bf4fcd1ed3b510c6860167dbd3bd4d099c6b8a78d2a767af
- initial_input_ast: 96ddbb84cba723df65571d6537a303189e6274389593980996fd7ee50eab996e
initial_ast: e17f5c2d253ffc1e8e3389253f89feca418b429eb912840a21172d63d117c7ec
symbol_table: f36863240edb9fb5fb852c212a9ae1db491ee8243d0469fc155592964595e7d0

View File

@ -3,9 +3,9 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 51b03881ad0ef3af7d105c163071fb69fb38048bea44c4bc380fd17367ce94e0
- initial_input_ast: 59b58754cc7667404c6bba5d90a9e53b7f9f36b6d7c9783e5b88d12728127e66
- initial_input_ast: 55ff7a9a3f210ea871c438a89f07da6c54ca1b8129e7344593017d22305297b4
- initial_input_ast: c89564770d1984e4e8c0c17c6c50b66b4a5d4ade85899562f506afc22e50496d
initial_ast: 73e2d3f95cac34a231f20df1de3c53fd08ae3d9e604ee28557c1098299e8170c
- initial_input_ast: e7e9fd77647ac56ed68e547bfb8d0c767313030072a510ec138027ffb62fc368
- initial_input_ast: e43c024d6fad8a7a04672fa318936703a4798699283f7b66d9383d52acc104a0
- initial_input_ast: 695d879ad212b23fb3e91fae782c701c5f0469bbcaabdcfc6e5dcadc5b7e6c9a
- initial_input_ast: 390e951d2b90cf150acd9bc6eeeffbc3a8d7af3ce3781f14ebdce3f1054de4c8
initial_ast: adb3d21c4da2e7538a95ba689373f870d370001c8fb60e38a96ed6e6cf87ae6c
symbol_table: 4fd4e476609947028fbffe357ffb9d962e96c30a9abe3677d75675ae37b12587

View File

@ -3,9 +3,9 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 51b03881ad0ef3af7d105c163071fb69fb38048bea44c4bc380fd17367ce94e0
- initial_input_ast: 59b58754cc7667404c6bba5d90a9e53b7f9f36b6d7c9783e5b88d12728127e66
- initial_input_ast: 55ff7a9a3f210ea871c438a89f07da6c54ca1b8129e7344593017d22305297b4
- initial_input_ast: c89564770d1984e4e8c0c17c6c50b66b4a5d4ade85899562f506afc22e50496d
initial_ast: 3c8d1d820525dc4e77214dfa0628a8fb73890ee1b90cfd443a4a736e6506bbad
- initial_input_ast: e6457724e4c3bb27eca30df861f711f962ac47fb0e7d0b9dc959be0feaeb7763
- initial_input_ast: c8d27a86795a6d56815a681066b7f462f5476be6d56ec910b74d90c60d8b3cc9
- initial_input_ast: 4ff2fb01e2d10a59bf4fcd1ed3b510c6860167dbd3bd4d099c6b8a78d2a767af
- initial_input_ast: 96ddbb84cba723df65571d6537a303189e6274389593980996fd7ee50eab996e
initial_ast: 487ec91d706447fafcff6e448723fa41dd02e6d8ea1b3b8670460ef9a7931c90
symbol_table: c8dd46774e298ef70fc87f89ecb8b5f23f63b1f2401f337fc97ad83b54e85871

View File

@ -3,9 +3,9 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 51b03881ad0ef3af7d105c163071fb69fb38048bea44c4bc380fd17367ce94e0
- initial_input_ast: 59b58754cc7667404c6bba5d90a9e53b7f9f36b6d7c9783e5b88d12728127e66
- initial_input_ast: 55ff7a9a3f210ea871c438a89f07da6c54ca1b8129e7344593017d22305297b4
- initial_input_ast: c89564770d1984e4e8c0c17c6c50b66b4a5d4ade85899562f506afc22e50496d
initial_ast: f94ce8212b4164b85de34920f7da472033fbafe03e8e1d00a0ec7f9bae692b6c
- initial_input_ast: e6457724e4c3bb27eca30df861f711f962ac47fb0e7d0b9dc959be0feaeb7763
- initial_input_ast: c8d27a86795a6d56815a681066b7f462f5476be6d56ec910b74d90c60d8b3cc9
- initial_input_ast: 4ff2fb01e2d10a59bf4fcd1ed3b510c6860167dbd3bd4d099c6b8a78d2a767af
- initial_input_ast: 96ddbb84cba723df65571d6537a303189e6274389593980996fd7ee50eab996e
initial_ast: 4c24b2ad645f55d42b011b1173fc756330dfa1df4734c2c3275ff53a364ba28c
symbol_table: 8ed9a73e996562abfe75837cfbf2103a4d9213291298206f4f63a7dac808cbc1

View File

@ -3,9 +3,9 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 51b03881ad0ef3af7d105c163071fb69fb38048bea44c4bc380fd17367ce94e0
- initial_input_ast: 59b58754cc7667404c6bba5d90a9e53b7f9f36b6d7c9783e5b88d12728127e66
- initial_input_ast: 55ff7a9a3f210ea871c438a89f07da6c54ca1b8129e7344593017d22305297b4
- initial_input_ast: c89564770d1984e4e8c0c17c6c50b66b4a5d4ade85899562f506afc22e50496d
initial_ast: ceac1c88ce7915eb171fef59cf7788b1d83cb53d313e0325b4b6e7ca7c0b0eea
- initial_input_ast: e6457724e4c3bb27eca30df861f711f962ac47fb0e7d0b9dc959be0feaeb7763
- initial_input_ast: c8d27a86795a6d56815a681066b7f462f5476be6d56ec910b74d90c60d8b3cc9
- initial_input_ast: 4ff2fb01e2d10a59bf4fcd1ed3b510c6860167dbd3bd4d099c6b8a78d2a767af
- initial_input_ast: 96ddbb84cba723df65571d6537a303189e6274389593980996fd7ee50eab996e
initial_ast: 69f7732147079d749ad863cb4442be4722f1b7eb16f26b7f972beed0d006044c
symbol_table: 91630eda77eaf1e355744e663ceba26a0c3f860d3f69e8e46b03f5464d16950f

View File

@ -3,20 +3,20 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: cd2c41435af95147ff1dcd94031e443b93b15ac7b4f65331ef734759006f3c03
- initial_input_ast: 5e4fd7cfc681e863ed393f7746308d7b962e2b5f9dcd21aa09a26526ce2ea8e3
- initial_input_ast: 8fcda0e92250e9897bdb8cfb9b1e3046f94f6f6206ecb958d9758e64e5615889
- initial_input_ast: 41fef97affd26b29428302f519a5e7a7d61158923e6576618c42607f0c16ff4f
- initial_input_ast: 30c56d9a2e096215900942f18b63cf5a96fb9c0b7cf4fea11dafeeabb02a5233
- initial_input_ast: 076d0f1b70534c15108ea0dc9e74860030d6701ce1ce38b4a3a41e5ba9fe0121
- initial_input_ast: d3bff6374e68b63bf35fe089bbff0abb31958571b99b9e0251d82895fdc27edd
- initial_input_ast: 9455652735eb74bd67423f9ed2c7d76b1b27e47f62b5331843f8f4975a03cc9a
- initial_input_ast: 3f69c5fdd03605808dfb6ae116cdf860525b494d5d7cac39b667931c282e8c3e
- initial_input_ast: bdc202a836d17bcb974e33b5b938148c0c9b57fd8b779e813c26d8feac915547
- initial_input_ast: 6e12715d32233251ea63ae7457c7c1d20e82995cf3df02a1adb943ee358a2643
- initial_input_ast: 6383f20ea72b337521956a9d86608fc1861f8a5e709bb29e88f2022e893d4e59
- initial_input_ast: e4ba1106bf3425f620578111bd3c63c0178dbc087ab4c90e873c5b9cc790f6bc
- initial_input_ast: 4c7f9b03dd308ff3981127c4c12adcb883fd8b3ce1dbd744cd935750961fc1c4
- initial_input_ast: 2a5e92af845c8a56375cbc6123e92aa87cf4523e059c02dfcde326970d88f5c2
initial_ast: 9733a36e7d3465c6217ecf2139c2e4154790e39f006f1e3318a981265d24ad23
- initial_input_ast: 1a59d72ff9c08c97f0faa7d32e701487abce48630c3da2ec76dee451ed806c3b
- initial_input_ast: 8c79c9fa5fa8422d837bd092a848293d1772fdc97b80c7394146fc759768c868
- initial_input_ast: cbf3cfc28c6c396dd5dd24ec3cb59121d2d6615feb4aa9a452ea310248dfb238
- initial_input_ast: 8a914ea590d1b978e7f0da8feeebcbe195e925a20424fe0a6611b2115b072c90
- initial_input_ast: f37e2792fd64626a0270041c37d587d4929ac2afe6b3b9a576c3ec400271f0db
- initial_input_ast: d9a2bd44fa3b8e850b79be10ab046af8d61b5e781cc991250969555eaccf9d23
- initial_input_ast: c10a3ffcb8bbbaaa3028e8037fc183214933291d5ecf8ec0354df1b27a83c99a
- initial_input_ast: 32628105ebaaed3207a26402f2f7a5075f2d7d865d51e56f2e8f0bade905058c
- initial_input_ast: 2bc88f79d4b48e6321c08ba4a6cfeb2a7363b238d79b3a558dbc4383c14a3ebc
- initial_input_ast: 5d6794f9c9406df4df4673433c806588bb9ed72992bb58cc62fa63a3a872e153
- initial_input_ast: 833c67bb4946711a01be5f564905d83eaf4c4fbc72ff77599ff3b8dd5a5c8691
- initial_input_ast: 2a4441d425a2e35c929d92256601e3713c870ef3c9c6206dccb238e42be532cb
- initial_input_ast: 3edf030ed195c3ab8278af07fa1592314e2e3f9ad1e6c0ca3e27856be5e6f72c
- initial_input_ast: f3dcb662ae0facb7afdd7cee9416261a48d37baa8a4d5d7f09d81e4621b53f3f
- initial_input_ast: aebc549a2d2d87e1cca5e6d814b1b6dfdc4c32bb21045ad967bc67978a8ef871
initial_ast: 8c9ec5e2c1544bc45c6d4dd9f21caa3121c2ba61c44fb66d8148883460b20820
symbol_table: cf3569155d9961e6cab441ea9a60f5c92d2b18e6cd2ecaa64b1529d1774d3585

View File

@ -3,20 +3,20 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: cd2c41435af95147ff1dcd94031e443b93b15ac7b4f65331ef734759006f3c03
- initial_input_ast: 5e4fd7cfc681e863ed393f7746308d7b962e2b5f9dcd21aa09a26526ce2ea8e3
- initial_input_ast: 8fcda0e92250e9897bdb8cfb9b1e3046f94f6f6206ecb958d9758e64e5615889
- initial_input_ast: 41fef97affd26b29428302f519a5e7a7d61158923e6576618c42607f0c16ff4f
- initial_input_ast: 30c56d9a2e096215900942f18b63cf5a96fb9c0b7cf4fea11dafeeabb02a5233
- initial_input_ast: 076d0f1b70534c15108ea0dc9e74860030d6701ce1ce38b4a3a41e5ba9fe0121
- initial_input_ast: d3bff6374e68b63bf35fe089bbff0abb31958571b99b9e0251d82895fdc27edd
- initial_input_ast: 9455652735eb74bd67423f9ed2c7d76b1b27e47f62b5331843f8f4975a03cc9a
- initial_input_ast: 3f69c5fdd03605808dfb6ae116cdf860525b494d5d7cac39b667931c282e8c3e
- initial_input_ast: bdc202a836d17bcb974e33b5b938148c0c9b57fd8b779e813c26d8feac915547
- initial_input_ast: 6e12715d32233251ea63ae7457c7c1d20e82995cf3df02a1adb943ee358a2643
- initial_input_ast: 6383f20ea72b337521956a9d86608fc1861f8a5e709bb29e88f2022e893d4e59
- initial_input_ast: e4ba1106bf3425f620578111bd3c63c0178dbc087ab4c90e873c5b9cc790f6bc
- initial_input_ast: 4c7f9b03dd308ff3981127c4c12adcb883fd8b3ce1dbd744cd935750961fc1c4
- initial_input_ast: 2a5e92af845c8a56375cbc6123e92aa87cf4523e059c02dfcde326970d88f5c2
initial_ast: 890e5d07cf4b2967be0e2f9c82268619015dc3cea62cc1520f406107cdd056e5
- initial_input_ast: 44e0b05b0da70ab554408e1fa7a8578282522b358320cde13231c2136e4df5b1
- initial_input_ast: fa8ef1a0d3743224c55ca78079611c87374266313d2254c5b18a99443e038d51
- initial_input_ast: 6aa65f48c47c0a70326ee6034a46c38ed25116b02b748827fde3a4a46cb9cb95
- initial_input_ast: de106cf7de15ce9b35d00a97dccf6b90077303e8bfcec568d65352107c2a81f8
- initial_input_ast: a6badf7eba50a21d6ebc1c82eb70cd4081e37680dd8d4b597ea04192ccbf4e5a
- initial_input_ast: 72e2f6ef3f3cb3135dbb46dd1c5808c206cfa762a708a8d5483b6bc2958a33ba
- initial_input_ast: 0a5209868d802596f6094912deb7adaef5f21e0ee269eeaa3a661d403a64701e
- initial_input_ast: be71fcee4adbb8c7de279825c5fd87d8c55597a97f57f9af28d88e3f51781c79
- initial_input_ast: 55aae45600898144d628c1211e2de07794ce4784eef21a6b978aa064d3fa89f4
- initial_input_ast: 8f73004838aee69e847d99ab0b284d99c61a8283b91227e1dd890994220da8e1
- initial_input_ast: 6de398471c245e863855e68b0b672bcda53467f638ccf2ded60930a930f3de25
- initial_input_ast: 1d22c4edd4f3fec707b8cb6e60bf57b4e278913fbb6c15c4fa2bce0e318de232
- initial_input_ast: 7642187a32f44ae4d5743ae8f46bb669937490ff926c46cf8af8b36b5bc747c5
- initial_input_ast: 4d7b20c6c94064e08e0f19b0f45cbdd740f668fefcafd361865226c5af087440
- initial_input_ast: 9de9e1877e523f5aa44d019bba11e7bb58ad1f9952aae3254908e8b151b3ae55
initial_ast: 526f77f4386ed6b5dd40f7e352f48e43c04655123bf329dbed9f6dadd43a4963
symbol_table: 1cad55eef598e4d05af7c5f88119636a2e6d23d81213bbaad908d66a32906780

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 204a90b23ba88927aabdc72aed02effa556d73742caf7d370527f79f0b30f621
initial_ast: 10539810602f7b65e0ac424d7e92b4565c965fdbe139b267f5fd4aae4c67d470
- initial_input_ast: 9698e866b0330be095c65ca93f17ed5fe3d31c61d5622eaf54c774d79d3b6950
initial_ast: d771cc51e9c822faf8cb1ca6f80d19c22379ac37c9ae9e357010e79029c6baf2
symbol_table: f8c971e501487f7a368a50fd1941c3fb70684b041478fe615a91f088796e301b

View File

@ -3,7 +3,7 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 204a90b23ba88927aabdc72aed02effa556d73742caf7d370527f79f0b30f621
- initial_input_ast: cbc36a842b21e80aee167b65bd1a59861d59a43e27915b785410f032ae19a570
initial_ast: 1e37339f631e947b4f85cf4f43ba4c1a26439ab565dc559f27c4923afc3ef34a
- initial_input_ast: e9253dc5764d8870dc6842860993ce0b2495925b3bdb18891b7c4aa67fe0a81d
- initial_input_ast: 3153e33ab1630d74ad221b5ce6d5e50c17fb86d91a2aae4ce67b46fec12c1ef4
initial_ast: 8fdb85c9c133687f89fe5c2ca9b177a4a777269eab425f9008ab330cce85542e
symbol_table: f4e056be00b25dfd854a5be8197aeb205436bb0ee11cfe06701531ea086e038c

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 38e6b369397fcf11fa921808be61baf33a705d4509bc15a46ec69e1a0aaa5031
initial_ast: 379919a368ef91f880f8209c68891ac5b5071c3d7f64ae15b39eaab52972d6a9
- initial_input_ast: 6b9e5227fdce9f916cd2398ea85c2d7e7b2f7d706bfa730b8cd1acdeb3f168cd
initial_ast: e3b69d0b4355afd331edf8c572b64746bc763a714626043a9edc8eba42b08ec8
symbol_table: d46f6eb98259f34d32a60788aa178efa34166bcc6ba1058e2ff5f8327a129b9c

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 38e6b369397fcf11fa921808be61baf33a705d4509bc15a46ec69e1a0aaa5031
initial_ast: c573c8914fc34302d6ea0ad1727f61b02c540f2f9dce82fd492407002516a367
- initial_input_ast: 89959164cbf734ac0d261c7459b9c1214eb2f4b3ab9ec57a0b22db487d6537e4
initial_ast: cb79b9db64a7e92b85706e517b586b4fe9cd591850e7130cc7bfad6dd92b4d3f
symbol_table: 559484bc163178bf54b169f5dd573167771566aa993055b6a28f0c1a759339bc

View File

@ -3,7 +3,7 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: b9ca1f9e4746ba9f99375205e309b977a522109054d058039197767b39fa6833
- initial_input_ast: 398a847f3f6c8826a10942c856b67d9acf37a51bf4ec9109be549b24b2dfff94
initial_ast: 29f607e8e1badfbb612a8acb20123882205c86c7290a24dca70df39f8261cc0b
- initial_input_ast: 4132cf36ac66f6b23e249f81b5c2aafa58e4e5e945920cc29752edc5d6d8057f
- initial_input_ast: 586ed72429932a1aafcd0f8eed983a4babff8eada9c028b88bbeef24dab1cbc0
initial_ast: 0360f7fba87784c290f73693b81ca1b71e3259794f0fb3d3cbe39cc143e92d82
symbol_table: 560afbb790df70bfc770d5c2f966428a37baf94a5c0f5312ad445456d33a2cd9

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 38e6b369397fcf11fa921808be61baf33a705d4509bc15a46ec69e1a0aaa5031
initial_ast: a5cf98065c1f1a668d898974ab67cd148e43409c0455d95f77e030cb5c905e0c
- initial_input_ast: 5411bd17943bb0aa7b0bb27e8b38f57fd27f06f2080b13a32eee50c53de66f6c
initial_ast: ab02de15b37b07d52d385468d72b03f8f9ecff3c9f130b8a3985be326f9f6edf
symbol_table: 720c2aafae77c261ed1640d4080f9a73657638baa30e54a5e10e2323b6f6eca0

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 38e6b369397fcf11fa921808be61baf33a705d4509bc15a46ec69e1a0aaa5031
initial_ast: 1b5cb8e6d851548c2413ef9d0e90bc46b70ee109655c5396522ae06a73832015
- initial_input_ast: 18e8a4118829470d3150268bbf8d298954e1f566ea2d42ed9f3660dc25c23fcc
initial_ast: 4fa505d3542f2df2abcdbbf7d487ff65e1e311366fc2eaee286f8ba253876883
symbol_table: e5159343ab03573032873783b28058a482dd401d534a0d3af03790a5286ba470

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 38e6b369397fcf11fa921808be61baf33a705d4509bc15a46ec69e1a0aaa5031
initial_ast: 620af027368aff6683ef9951f714867e1c53d335621b549978177c0951a67ecb
- initial_input_ast: caa45de3b412d749048b9be732a4593f3094c671701093103f580817a741acbb
initial_ast: 8dc13a9cb4d48b8a5e33d4e16a3071869a6ac7034962af5baf8f5f19a2b218dd
symbol_table: 757bb967973b87466c01be1a9dc78d30701964e0d234e0e65d1bbcbd3072370f

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 3674d8249023145121ff35eb4d9e59b0ce79cda7e17f9f98b5dbaa6ba4f80cf2
initial_ast: ea05e8a68b86c5cd7189870b309bb5a4107dd6f84c9ccd359aacbfee82045242
- initial_input_ast: 4a7171bfd4cb5b69729e26e4c6b0915f261d3f51b2937d8de5009069f56abfc1
initial_ast: 8b6fdc73a1397af850bcb47a623f82ff773919308fec52eeb890c8b4a2e686e7
symbol_table: 66779461e33acc9c5c732509637db91bd72aff3e9dae6aee0c137d0537446878

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 3a50bcc0c4416f93de77861848ac00cd1b40e17f4c023ab3faea0fc0c332f148
initial_ast: e0c7874ac5b43acb60bfb111cfafba0b5151b202f86c459913a9d4dd8ca151b0
- initial_input_ast: 770cad45d17364fd3acd19fb67c66ea8f58ea54c5c42386d1a0fe02f241e9f2b
initial_ast: 5c6f3087ccb1ce8c559638d4a4308a784a1a69735fd3a4cbd7eccdcb6b76aeb7
symbol_table: d666098c1c0d7c670730cfa6548d47fa89d9a1dd33642f8021b0622f9abc0e5e

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 3a50bcc0c4416f93de77861848ac00cd1b40e17f4c023ab3faea0fc0c332f148
initial_ast: 149443378c6b75f71b33ad90306cf4b01616284ddfa2136fc19fe41e23c73178
- initial_input_ast: 3b1682d80f44da8eb1ea0d1236b5b9be15f7d4792fe7f31139a4362b2952d6a0
initial_ast: cda0e01cadbcd6488f11d1a79fd9e4d132560ff75dad986cb4502d74f3e464be
symbol_table: 38cbfecf35fb5189618a9767d3245d02e133d59ce2a0fc0f3aba37a8fa14fe8e

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 3a50bcc0c4416f93de77861848ac00cd1b40e17f4c023ab3faea0fc0c332f148
initial_ast: 51eba8b00503b23218feec128cda498464acd2a9459fc717795d4137495a9820
- initial_input_ast: 1d6d705c0d5363431af8b58173f1061d4315c4ffe9ae175d6dd1c7ea2a01488f
initial_ast: fa376065aea93f4819afe923b978fd8addc4565c13b33cef8416cdd599f331b2
symbol_table: 0879cd6e4cc609ecdbdfc87ff0f08b4f3ae54367e0a1c02116304eb1411d2c23

Some files were not shown because too many files have changed in this diff Show More