Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(prelude_import)]
- #![feature(fmt_internals)]
- #![feature(fmt_helpers_for_derive)]
- #![feature(print_internals)]
- #![feature(core_intrinsics)]
- #![feature(core_panic)]
- #![feature(derive_clone_copy)]
- #![feature(structural_match)]
- #![feature(no_coverage)]
- #![feature(derive_eq)]
- #![feature(rustc_attrs)]
- #[prelude_import]
- use std::prelude::rust_2021::*;
- #[macro_use]
- extern crate std;
- extern crate alloc;
- use crate::interp::Interpreter;
- use crate::session::Session;
- mod analyzer {
- use crate::ast::{Stmt, StmtContainer};
- use crate::diagnostics::{Diagnostic, ErrorCode, Severity, Span};
- use std::cell::RefCell;
- pub struct Analyzer<'tcx> {
- ast: &'tcx [StmtContainer],
- context: RefCell<AnalyzerContext>,
- }
- struct AnalyzerContext {
- diagnostics: Vec<Diagnostic>,
- context: Vec<Context>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for AnalyzerContext {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "AnalyzerContext",
- "diagnostics",
- &&self.diagnostics,
- "context",
- &&self.context,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for AnalyzerContext {
- #[inline]
- fn clone(&self) -> AnalyzerContext {
- AnalyzerContext {
- diagnostics: ::core::clone::Clone::clone(&self.diagnostics),
- context: ::core::clone::Clone::clone(&self.context),
- }
- }
- }
- impl<'tcx> Analyzer<'tcx> {
- pub fn new(ast: &'tcx [StmtContainer]) -> Self {
- Self {
- ast,
- context: RefCell::new(AnalyzerContext {
- diagnostics: alloc::vec::Vec::new(),
- context: <[_]>::into_vec(
- #[rustc_box]
- alloc::boxed::Box::new([Context::Root]),
- ),
- }),
- }
- }
- pub fn analyze(&self) {
- for stmt in self.ast {
- self.analyze_stmt(stmt);
- }
- }
- fn get_block_stmt<'a>(&'a self, stmt: &'a Stmt) -> &'a [StmtContainer] {
- match stmt {
- Stmt::Block(stmts) => stmts,
- _ => ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["Cannot get block stmt from non block stmt"],
- &[],
- )),
- }
- }
- fn analyze_stmt(&self, stmt: &StmtContainer) {
- match &stmt.stmt {
- Stmt::Fun(fun_stmt) => {
- self.context
- .borrow_mut()
- .context
- .push(Context::Fun(stmt.span));
- for stmt in self.get_block_stmt(&fun_stmt.body.stmt) {
- self.analyze_stmt(stmt);
- }
- self.context.borrow_mut().context.pop();
- }
- Stmt::Data(_) => {}
- Stmt::Methods(method_stmt) => {
- for method in &method_stmt.methods {
- self.context
- .borrow_mut()
- .context
- .push(Context::Method(method.span));
- self.analyze_stmt(method);
- self.context.borrow_mut().context.pop();
- }
- }
- Stmt::If(if_stmt) => {
- let body = self.get_block_stmt(&if_stmt.block.stmt);
- for stmt in body {
- self.analyze_stmt(stmt);
- }
- if let Some(then) = &if_stmt.then {
- self.analyze_stmt(then);
- }
- if let Some(else_) = &if_stmt.else_ {
- let body = self.get_block_stmt(match &else_.stmt {
- Stmt::If(if_stmt) => &if_stmt.block.stmt,
- _ => {
- ::core::panicking::panic("internal error: entered unreachable code")
- }
- });
- for stmt in body {
- self.analyze_stmt(stmt);
- }
- }
- }
- Stmt::Loop(loop_stmt) => {
- self.context
- .borrow_mut()
- .context
- .push(Context::Loop(stmt.span));
- for stmt in self.get_block_stmt(&loop_stmt.stmt) {
- self.analyze_stmt(stmt);
- }
- self.context.borrow_mut().context.pop();
- }
- Stmt::Iter(iter_stmt) => {
- self.context
- .borrow_mut()
- .context
- .push(Context::Loop(stmt.span));
- for stmt in self.get_block_stmt(&iter_stmt.block.stmt) {
- self.analyze_stmt(stmt);
- }
- self.context.borrow_mut().context.pop();
- }
- Stmt::Continue | Stmt::Break => {
- if !match self.context.borrow_mut().context.last() {
- Some(Context::Loop(_)) => true,
- _ => false,
- } {
- self.context.borrow_mut().diagnostics.push(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidLoopControl,
- message: String::from("Found `continue` or `break` outside loop"),
- span: stmt.span,
- });
- }
- }
- _ => (),
- }
- }
- pub fn get_diagnostics(self) -> Vec<Diagnostic> {
- self.context.into_inner().diagnostics
- }
- }
- enum Context {
- Root,
- Fun(Span),
- Method(Span),
- Loop(Span),
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Context {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Context::Root => ::core::fmt::Formatter::write_str(f, "Root"),
- Context::Fun(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Fun", &__self_0)
- }
- Context::Method(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Method", &__self_0)
- }
- Context::Loop(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Loop", &__self_0)
- }
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Context {
- #[inline]
- fn clone(&self) -> Context {
- let _: ::core::clone::AssertParamIsClone<Span>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Context {}
- #[automatically_derived]
- impl ::core::cmp::Ord for Context {
- #[inline]
- fn cmp(&self, other: &Context) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) {
- ::core::cmp::Ordering::Equal => match (self, other) {
- (Context::Fun(__self_0), Context::Fun(__arg1_0)) => {
- ::core::cmp::Ord::cmp(__self_0, __arg1_0)
- }
- (Context::Method(__self_0), Context::Method(__arg1_0)) => {
- ::core::cmp::Ord::cmp(__self_0, __arg1_0)
- }
- (Context::Loop(__self_0), Context::Loop(__arg1_0)) => {
- ::core::cmp::Ord::cmp(__self_0, __arg1_0)
- }
- _ => ::core::cmp::Ordering::Equal,
- },
- cmp => cmp,
- }
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for Context {
- #[inline]
- fn partial_cmp(&self, other: &Context) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) => match (self, other) {
- (Context::Fun(__self_0), Context::Fun(__arg1_0)) => {
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
- }
- (Context::Method(__self_0), Context::Method(__arg1_0)) => {
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
- }
- (Context::Loop(__self_0), Context::Loop(__arg1_0)) => {
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
- }
- _ => ::core::option::Option::Some(::core::cmp::Ordering::Equal),
- },
- cmp => cmp,
- }
- }
- }
- impl ::core::marker::StructuralEq for Context {}
- #[automatically_derived]
- impl ::core::cmp::Eq for Context {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<Span>;
- }
- }
- impl ::core::marker::StructuralPartialEq for Context {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Context {
- #[inline]
- fn eq(&self, other: &Context) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- && match (self, other) {
- (Context::Fun(__self_0), Context::Fun(__arg1_0)) => *__self_0 == *__arg1_0,
- (Context::Method(__self_0), Context::Method(__arg1_0)) => {
- *__self_0 == *__arg1_0
- }
- (Context::Loop(__self_0), Context::Loop(__arg1_0)) => *__self_0 == *__arg1_0,
- _ => true,
- }
- }
- #[inline]
- fn ne(&self, other: &Context) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag != __arg1_tag
- || match (self, other) {
- (Context::Fun(__self_0), Context::Fun(__arg1_0)) => *__self_0 != *__arg1_0,
- (Context::Method(__self_0), Context::Method(__arg1_0)) => {
- *__self_0 != *__arg1_0
- }
- (Context::Loop(__self_0), Context::Loop(__arg1_0)) => *__self_0 != *__arg1_0,
- _ => false,
- }
- }
- }
- }
- mod ast {
- use crate::diagnostics::Span;
- use crate::interner::InternedString;
- use crate::lexer::{NumberKind, TokenKind};
- use std::collections::HashMap;
- pub struct StmtContainer {
- pub stmt: Stmt,
- pub span: Span,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for StmtContainer {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "StmtContainer",
- "stmt",
- &&self.stmt,
- "span",
- &&self.span,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for StmtContainer {
- #[inline]
- fn clone(&self) -> StmtContainer {
- StmtContainer {
- stmt: ::core::clone::Clone::clone(&self.stmt),
- span: ::core::clone::Clone::clone(&self.span),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for StmtContainer {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for StmtContainer {
- #[inline]
- fn eq(&self, other: &StmtContainer) -> bool {
- self.stmt == other.stmt && self.span == other.span
- }
- #[inline]
- fn ne(&self, other: &StmtContainer) -> bool {
- self.stmt != other.stmt || self.span != other.span
- }
- }
- impl StmtContainer {
- pub fn new(stmt: Stmt, span: Span) -> Self {
- Self { stmt, span }
- }
- }
- pub enum Stmt {
- Var(Box<VarStmt>),
- Fun(Box<FunStmt>),
- Data(Box<DataStmt>),
- Methods(Box<MethodsStmt>),
- Block(Vec<StmtContainer>),
- Loop(Box<StmtContainer>),
- Iter(Box<IterStmt>),
- If(Box<IfStmt>),
- Expr(ExprContainer),
- Ret(ExprContainer),
- Continue,
- Break,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Stmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Stmt::Var(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Var", &__self_0)
- }
- Stmt::Fun(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Fun", &__self_0)
- }
- Stmt::Data(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Data", &__self_0)
- }
- Stmt::Methods(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Methods", &__self_0)
- }
- Stmt::Block(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Block", &__self_0)
- }
- Stmt::Loop(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Loop", &__self_0)
- }
- Stmt::Iter(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Iter", &__self_0)
- }
- Stmt::If(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "If", &__self_0)
- }
- Stmt::Expr(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Expr", &__self_0)
- }
- Stmt::Ret(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ret", &__self_0)
- }
- Stmt::Continue => ::core::fmt::Formatter::write_str(f, "Continue"),
- Stmt::Break => ::core::fmt::Formatter::write_str(f, "Break"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Stmt {
- #[inline]
- fn clone(&self) -> Stmt {
- match self {
- Stmt::Var(__self_0) => Stmt::Var(::core::clone::Clone::clone(__self_0)),
- Stmt::Fun(__self_0) => Stmt::Fun(::core::clone::Clone::clone(__self_0)),
- Stmt::Data(__self_0) => Stmt::Data(::core::clone::Clone::clone(__self_0)),
- Stmt::Methods(__self_0) => Stmt::Methods(::core::clone::Clone::clone(__self_0)),
- Stmt::Block(__self_0) => Stmt::Block(::core::clone::Clone::clone(__self_0)),
- Stmt::Loop(__self_0) => Stmt::Loop(::core::clone::Clone::clone(__self_0)),
- Stmt::Iter(__self_0) => Stmt::Iter(::core::clone::Clone::clone(__self_0)),
- Stmt::If(__self_0) => Stmt::If(::core::clone::Clone::clone(__self_0)),
- Stmt::Expr(__self_0) => Stmt::Expr(::core::clone::Clone::clone(__self_0)),
- Stmt::Ret(__self_0) => Stmt::Ret(::core::clone::Clone::clone(__self_0)),
- Stmt::Continue => Stmt::Continue,
- Stmt::Break => Stmt::Break,
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for Stmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Stmt {
- #[inline]
- fn eq(&self, other: &Stmt) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- && match (self, other) {
- (Stmt::Var(__self_0), Stmt::Var(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Fun(__self_0), Stmt::Fun(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Data(__self_0), Stmt::Data(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Methods(__self_0), Stmt::Methods(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Block(__self_0), Stmt::Block(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Loop(__self_0), Stmt::Loop(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Iter(__self_0), Stmt::Iter(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::If(__self_0), Stmt::If(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Expr(__self_0), Stmt::Expr(__arg1_0)) => *__self_0 == *__arg1_0,
- (Stmt::Ret(__self_0), Stmt::Ret(__arg1_0)) => *__self_0 == *__arg1_0,
- _ => true,
- }
- }
- #[inline]
- fn ne(&self, other: &Stmt) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag != __arg1_tag
- || match (self, other) {
- (Stmt::Var(__self_0), Stmt::Var(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Fun(__self_0), Stmt::Fun(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Data(__self_0), Stmt::Data(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Methods(__self_0), Stmt::Methods(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Block(__self_0), Stmt::Block(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Loop(__self_0), Stmt::Loop(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Iter(__self_0), Stmt::Iter(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::If(__self_0), Stmt::If(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Expr(__self_0), Stmt::Expr(__arg1_0)) => *__self_0 != *__arg1_0,
- (Stmt::Ret(__self_0), Stmt::Ret(__arg1_0)) => *__self_0 != *__arg1_0,
- _ => false,
- }
- }
- }
- impl Stmt {
- pub fn into_container(self, span: Span) -> StmtContainer {
- StmtContainer { stmt: self, span }
- }
- }
- pub struct IfStmt {
- pub condition: ExprContainer,
- pub block: StmtContainer,
- pub else_: Option<StmtContainer>,
- pub then: Option<StmtContainer>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for IfStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field4_finish(
- f,
- "IfStmt",
- "condition",
- &&self.condition,
- "block",
- &&self.block,
- "else_",
- &&self.else_,
- "then",
- &&self.then,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for IfStmt {
- #[inline]
- fn clone(&self) -> IfStmt {
- IfStmt {
- condition: ::core::clone::Clone::clone(&self.condition),
- block: ::core::clone::Clone::clone(&self.block),
- else_: ::core::clone::Clone::clone(&self.else_),
- then: ::core::clone::Clone::clone(&self.then),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for IfStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for IfStmt {
- #[inline]
- fn eq(&self, other: &IfStmt) -> bool {
- self.condition == other.condition
- && self.block == other.block
- && self.else_ == other.else_
- && self.then == other.then
- }
- #[inline]
- fn ne(&self, other: &IfStmt) -> bool {
- self.condition != other.condition
- || self.block != other.block
- || self.else_ != other.else_
- || self.then != other.then
- }
- }
- pub struct IterStmt {
- pub iterable: ExprContainer,
- pub binding: InternedString,
- pub block: StmtContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for IterStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "IterStmt",
- "iterable",
- &&self.iterable,
- "binding",
- &&self.binding,
- "block",
- &&self.block,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for IterStmt {
- #[inline]
- fn clone(&self) -> IterStmt {
- IterStmt {
- iterable: ::core::clone::Clone::clone(&self.iterable),
- binding: ::core::clone::Clone::clone(&self.binding),
- block: ::core::clone::Clone::clone(&self.block),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for IterStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for IterStmt {
- #[inline]
- fn eq(&self, other: &IterStmt) -> bool {
- self.iterable == other.iterable
- && self.binding == other.binding
- && self.block == other.block
- }
- #[inline]
- fn ne(&self, other: &IterStmt) -> bool {
- self.iterable != other.iterable
- || self.binding != other.binding
- || self.block != other.block
- }
- }
- pub struct VarStmt {
- pub name: InternedString,
- pub value: ExprContainer,
- pub mutable: Mutable,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for VarStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "VarStmt",
- "name",
- &&self.name,
- "value",
- &&self.value,
- "mutable",
- &&self.mutable,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for VarStmt {
- #[inline]
- fn clone(&self) -> VarStmt {
- VarStmt {
- name: ::core::clone::Clone::clone(&self.name),
- value: ::core::clone::Clone::clone(&self.value),
- mutable: ::core::clone::Clone::clone(&self.mutable),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for VarStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for VarStmt {
- #[inline]
- fn eq(&self, other: &VarStmt) -> bool {
- self.name == other.name && self.value == other.value && self.mutable == other.mutable
- }
- #[inline]
- fn ne(&self, other: &VarStmt) -> bool {
- self.name != other.name || self.value != other.value || self.mutable != other.mutable
- }
- }
- pub enum Mutable {
- Yes,
- No,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Mutable {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Mutable::Yes => ::core::fmt::Formatter::write_str(f, "Yes"),
- Mutable::No => ::core::fmt::Formatter::write_str(f, "No"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Mutable {
- #[inline]
- fn clone(&self) -> Mutable {
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Mutable {}
- impl ::core::marker::StructuralPartialEq for Mutable {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Mutable {
- #[inline]
- fn eq(&self, other: &Mutable) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- pub struct FunStmt {
- pub name: InternedString,
- pub arguments: Vec<InternedString>,
- pub body: StmtContainer,
- pub is_method: bool,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for FunStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field4_finish(
- f,
- "FunStmt",
- "name",
- &&self.name,
- "arguments",
- &&self.arguments,
- "body",
- &&self.body,
- "is_method",
- &&self.is_method,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for FunStmt {
- #[inline]
- fn clone(&self) -> FunStmt {
- FunStmt {
- name: ::core::clone::Clone::clone(&self.name),
- arguments: ::core::clone::Clone::clone(&self.arguments),
- body: ::core::clone::Clone::clone(&self.body),
- is_method: ::core::clone::Clone::clone(&self.is_method),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for FunStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for FunStmt {
- #[inline]
- fn eq(&self, other: &FunStmt) -> bool {
- self.name == other.name
- && self.arguments == other.arguments
- && self.body == other.body
- && self.is_method == other.is_method
- }
- #[inline]
- fn ne(&self, other: &FunStmt) -> bool {
- self.name != other.name
- || self.arguments != other.arguments
- || self.body != other.body
- || self.is_method != other.is_method
- }
- }
- pub struct DataStmt {
- pub name: InternedString,
- pub fields: Vec<InternedString>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for DataStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "DataStmt",
- "name",
- &&self.name,
- "fields",
- &&self.fields,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for DataStmt {
- #[inline]
- fn clone(&self) -> DataStmt {
- DataStmt {
- name: ::core::clone::Clone::clone(&self.name),
- fields: ::core::clone::Clone::clone(&self.fields),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for DataStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for DataStmt {
- #[inline]
- fn eq(&self, other: &DataStmt) -> bool {
- self.name == other.name && self.fields == other.fields
- }
- #[inline]
- fn ne(&self, other: &DataStmt) -> bool {
- self.name != other.name || self.fields != other.fields
- }
- }
- pub struct MethodsStmt {
- pub data: InternedString,
- pub methods: Vec<StmtContainer>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for MethodsStmt {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "MethodsStmt",
- "data",
- &&self.data,
- "methods",
- &&self.methods,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for MethodsStmt {
- #[inline]
- fn clone(&self) -> MethodsStmt {
- MethodsStmt {
- data: ::core::clone::Clone::clone(&self.data),
- methods: ::core::clone::Clone::clone(&self.methods),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for MethodsStmt {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for MethodsStmt {
- #[inline]
- fn eq(&self, other: &MethodsStmt) -> bool {
- self.data == other.data && self.methods == other.methods
- }
- #[inline]
- fn ne(&self, other: &MethodsStmt) -> bool {
- self.data != other.data || self.methods != other.methods
- }
- }
- pub struct ExprContainer {
- pub expr: Expr,
- pub span: Span,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for ExprContainer {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "ExprContainer",
- "expr",
- &&self.expr,
- "span",
- &&self.span,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for ExprContainer {
- #[inline]
- fn clone(&self) -> ExprContainer {
- ExprContainer {
- expr: ::core::clone::Clone::clone(&self.expr),
- span: ::core::clone::Clone::clone(&self.span),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for ExprContainer {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for ExprContainer {
- #[inline]
- fn eq(&self, other: &ExprContainer) -> bool {
- self.expr == other.expr && self.span == other.span
- }
- #[inline]
- fn ne(&self, other: &ExprContainer) -> bool {
- self.expr != other.expr || self.span != other.span
- }
- }
- pub enum Expr {
- Data(Box<DataExpr>),
- Assignment(Box<AssignmentExpr>),
- Get(Box<GetExpr>),
- Index(Box<IndexExpr>),
- IndexSet(Box<IndexSetExpr>),
- Set(Box<SetExpr>),
- Logical(Box<LogicalExpr>),
- Binary(Box<BinaryExpr>),
- Unary(Box<UnaryExpr>),
- Call(Box<CallExpr>),
- Boolean(bool),
- None,
- String(InternedString),
- Number(NumberExpr),
- Grouping(Box<ExprContainer>),
- Array(Vec<ExprContainer>),
- Variable(InternedString),
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Expr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Expr::Data(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Data", &__self_0)
- }
- Expr::Assignment(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Assignment", &__self_0)
- }
- Expr::Get(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Get", &__self_0)
- }
- Expr::Index(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Index", &__self_0)
- }
- Expr::IndexSet(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "IndexSet", &__self_0)
- }
- Expr::Set(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Set", &__self_0)
- }
- Expr::Logical(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Logical", &__self_0)
- }
- Expr::Binary(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Binary", &__self_0)
- }
- Expr::Unary(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unary", &__self_0)
- }
- Expr::Call(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Call", &__self_0)
- }
- Expr::Boolean(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Boolean", &__self_0)
- }
- Expr::None => ::core::fmt::Formatter::write_str(f, "None"),
- Expr::String(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "String", &__self_0)
- }
- Expr::Number(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Number", &__self_0)
- }
- Expr::Grouping(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Grouping", &__self_0)
- }
- Expr::Array(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Array", &__self_0)
- }
- Expr::Variable(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Variable", &__self_0)
- }
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Expr {
- #[inline]
- fn clone(&self) -> Expr {
- match self {
- Expr::Data(__self_0) => Expr::Data(::core::clone::Clone::clone(__self_0)),
- Expr::Assignment(__self_0) => {
- Expr::Assignment(::core::clone::Clone::clone(__self_0))
- }
- Expr::Get(__self_0) => Expr::Get(::core::clone::Clone::clone(__self_0)),
- Expr::Index(__self_0) => Expr::Index(::core::clone::Clone::clone(__self_0)),
- Expr::IndexSet(__self_0) => Expr::IndexSet(::core::clone::Clone::clone(__self_0)),
- Expr::Set(__self_0) => Expr::Set(::core::clone::Clone::clone(__self_0)),
- Expr::Logical(__self_0) => Expr::Logical(::core::clone::Clone::clone(__self_0)),
- Expr::Binary(__self_0) => Expr::Binary(::core::clone::Clone::clone(__self_0)),
- Expr::Unary(__self_0) => Expr::Unary(::core::clone::Clone::clone(__self_0)),
- Expr::Call(__self_0) => Expr::Call(::core::clone::Clone::clone(__self_0)),
- Expr::Boolean(__self_0) => Expr::Boolean(::core::clone::Clone::clone(__self_0)),
- Expr::None => Expr::None,
- Expr::String(__self_0) => Expr::String(::core::clone::Clone::clone(__self_0)),
- Expr::Number(__self_0) => Expr::Number(::core::clone::Clone::clone(__self_0)),
- Expr::Grouping(__self_0) => Expr::Grouping(::core::clone::Clone::clone(__self_0)),
- Expr::Array(__self_0) => Expr::Array(::core::clone::Clone::clone(__self_0)),
- Expr::Variable(__self_0) => Expr::Variable(::core::clone::Clone::clone(__self_0)),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for Expr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Expr {
- #[inline]
- fn eq(&self, other: &Expr) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- && match (self, other) {
- (Expr::Data(__self_0), Expr::Data(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Assignment(__self_0), Expr::Assignment(__arg1_0)) => {
- *__self_0 == *__arg1_0
- }
- (Expr::Get(__self_0), Expr::Get(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Index(__self_0), Expr::Index(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::IndexSet(__self_0), Expr::IndexSet(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Set(__self_0), Expr::Set(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Logical(__self_0), Expr::Logical(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Binary(__self_0), Expr::Binary(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Unary(__self_0), Expr::Unary(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Call(__self_0), Expr::Call(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Boolean(__self_0), Expr::Boolean(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::String(__self_0), Expr::String(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Number(__self_0), Expr::Number(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Grouping(__self_0), Expr::Grouping(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Array(__self_0), Expr::Array(__arg1_0)) => *__self_0 == *__arg1_0,
- (Expr::Variable(__self_0), Expr::Variable(__arg1_0)) => *__self_0 == *__arg1_0,
- _ => true,
- }
- }
- #[inline]
- fn ne(&self, other: &Expr) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag != __arg1_tag
- || match (self, other) {
- (Expr::Data(__self_0), Expr::Data(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Assignment(__self_0), Expr::Assignment(__arg1_0)) => {
- *__self_0 != *__arg1_0
- }
- (Expr::Get(__self_0), Expr::Get(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Index(__self_0), Expr::Index(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::IndexSet(__self_0), Expr::IndexSet(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Set(__self_0), Expr::Set(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Logical(__self_0), Expr::Logical(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Binary(__self_0), Expr::Binary(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Unary(__self_0), Expr::Unary(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Call(__self_0), Expr::Call(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Boolean(__self_0), Expr::Boolean(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::String(__self_0), Expr::String(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Number(__self_0), Expr::Number(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Grouping(__self_0), Expr::Grouping(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Array(__self_0), Expr::Array(__arg1_0)) => *__self_0 != *__arg1_0,
- (Expr::Variable(__self_0), Expr::Variable(__arg1_0)) => *__self_0 != *__arg1_0,
- _ => false,
- }
- }
- }
- impl Expr {
- pub fn into_container(self, span: Span) -> ExprContainer {
- ExprContainer { expr: self, span }
- }
- }
- pub struct DataExpr {
- pub name: InternedString,
- pub props: HashMap<InternedString, ExprContainer>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for DataExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "DataExpr",
- "name",
- &&self.name,
- "props",
- &&self.props,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for DataExpr {
- #[inline]
- fn clone(&self) -> DataExpr {
- DataExpr {
- name: ::core::clone::Clone::clone(&self.name),
- props: ::core::clone::Clone::clone(&self.props),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for DataExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for DataExpr {
- #[inline]
- fn eq(&self, other: &DataExpr) -> bool {
- self.name == other.name && self.props == other.props
- }
- #[inline]
- fn ne(&self, other: &DataExpr) -> bool {
- self.name != other.name || self.props != other.props
- }
- }
- pub struct AssignmentExpr {
- pub lvalue: ExprContainer,
- pub rvalue: ExprContainer,
- pub data_member: bool,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for AssignmentExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "AssignmentExpr",
- "lvalue",
- &&self.lvalue,
- "rvalue",
- &&self.rvalue,
- "data_member",
- &&self.data_member,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for AssignmentExpr {
- #[inline]
- fn clone(&self) -> AssignmentExpr {
- AssignmentExpr {
- lvalue: ::core::clone::Clone::clone(&self.lvalue),
- rvalue: ::core::clone::Clone::clone(&self.rvalue),
- data_member: ::core::clone::Clone::clone(&self.data_member),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for AssignmentExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for AssignmentExpr {
- #[inline]
- fn eq(&self, other: &AssignmentExpr) -> bool {
- self.lvalue == other.lvalue
- && self.rvalue == other.rvalue
- && self.data_member == other.data_member
- }
- #[inline]
- fn ne(&self, other: &AssignmentExpr) -> bool {
- self.lvalue != other.lvalue
- || self.rvalue != other.rvalue
- || self.data_member != other.data_member
- }
- }
- pub struct GetExpr {
- pub property: InternedString,
- pub object: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for GetExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "GetExpr",
- "property",
- &&self.property,
- "object",
- &&self.object,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for GetExpr {
- #[inline]
- fn clone(&self) -> GetExpr {
- GetExpr {
- property: ::core::clone::Clone::clone(&self.property),
- object: ::core::clone::Clone::clone(&self.object),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for GetExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for GetExpr {
- #[inline]
- fn eq(&self, other: &GetExpr) -> bool {
- self.property == other.property && self.object == other.object
- }
- #[inline]
- fn ne(&self, other: &GetExpr) -> bool {
- self.property != other.property || self.object != other.object
- }
- }
- pub struct IndexExpr {
- pub index: ExprContainer,
- pub object: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for IndexExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "IndexExpr",
- "index",
- &&self.index,
- "object",
- &&self.object,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for IndexExpr {
- #[inline]
- fn clone(&self) -> IndexExpr {
- IndexExpr {
- index: ::core::clone::Clone::clone(&self.index),
- object: ::core::clone::Clone::clone(&self.object),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for IndexExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for IndexExpr {
- #[inline]
- fn eq(&self, other: &IndexExpr) -> bool {
- self.index == other.index && self.object == other.object
- }
- #[inline]
- fn ne(&self, other: &IndexExpr) -> bool {
- self.index != other.index || self.object != other.object
- }
- }
- pub struct IndexSetExpr {
- pub object: ExprContainer,
- pub value: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for IndexSetExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "IndexSetExpr",
- "object",
- &&self.object,
- "value",
- &&self.value,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for IndexSetExpr {
- #[inline]
- fn clone(&self) -> IndexSetExpr {
- IndexSetExpr {
- object: ::core::clone::Clone::clone(&self.object),
- value: ::core::clone::Clone::clone(&self.value),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for IndexSetExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for IndexSetExpr {
- #[inline]
- fn eq(&self, other: &IndexSetExpr) -> bool {
- self.object == other.object && self.value == other.value
- }
- #[inline]
- fn ne(&self, other: &IndexSetExpr) -> bool {
- self.object != other.object || self.value != other.value
- }
- }
- pub struct SetExpr {
- pub object: ExprContainer,
- pub property: InternedString,
- pub value: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for SetExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "SetExpr",
- "object",
- &&self.object,
- "property",
- &&self.property,
- "value",
- &&self.value,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for SetExpr {
- #[inline]
- fn clone(&self) -> SetExpr {
- SetExpr {
- object: ::core::clone::Clone::clone(&self.object),
- property: ::core::clone::Clone::clone(&self.property),
- value: ::core::clone::Clone::clone(&self.value),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for SetExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for SetExpr {
- #[inline]
- fn eq(&self, other: &SetExpr) -> bool {
- self.object == other.object
- && self.property == other.property
- && self.value == other.value
- }
- #[inline]
- fn ne(&self, other: &SetExpr) -> bool {
- self.object != other.object
- || self.property != other.property
- || self.value != other.value
- }
- }
- pub struct LogicalExpr {
- pub lhs: ExprContainer,
- pub op: LogicalOperation,
- pub rhs: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for LogicalExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "LogicalExpr",
- "lhs",
- &&self.lhs,
- "op",
- &&self.op,
- "rhs",
- &&self.rhs,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for LogicalExpr {
- #[inline]
- fn clone(&self) -> LogicalExpr {
- LogicalExpr {
- lhs: ::core::clone::Clone::clone(&self.lhs),
- op: ::core::clone::Clone::clone(&self.op),
- rhs: ::core::clone::Clone::clone(&self.rhs),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for LogicalExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for LogicalExpr {
- #[inline]
- fn eq(&self, other: &LogicalExpr) -> bool {
- self.lhs == other.lhs && self.op == other.op && self.rhs == other.rhs
- }
- #[inline]
- fn ne(&self, other: &LogicalExpr) -> bool {
- self.lhs != other.lhs || self.op != other.op || self.rhs != other.rhs
- }
- }
- pub enum LogicalOperation {
- And,
- Or,
- Equals,
- NotEquals,
- GreaterThan,
- GreaterThanOrEquals,
- LessThan,
- LessThanOrEquals,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for LogicalOperation {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- LogicalOperation::And => ::core::fmt::Formatter::write_str(f, "And"),
- LogicalOperation::Or => ::core::fmt::Formatter::write_str(f, "Or"),
- LogicalOperation::Equals => ::core::fmt::Formatter::write_str(f, "Equals"),
- LogicalOperation::NotEquals => ::core::fmt::Formatter::write_str(f, "NotEquals"),
- LogicalOperation::GreaterThan => {
- ::core::fmt::Formatter::write_str(f, "GreaterThan")
- }
- LogicalOperation::GreaterThanOrEquals => {
- ::core::fmt::Formatter::write_str(f, "GreaterThanOrEquals")
- }
- LogicalOperation::LessThan => ::core::fmt::Formatter::write_str(f, "LessThan"),
- LogicalOperation::LessThanOrEquals => {
- ::core::fmt::Formatter::write_str(f, "LessThanOrEquals")
- }
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for LogicalOperation {
- #[inline]
- fn clone(&self) -> LogicalOperation {
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for LogicalOperation {}
- impl ::core::marker::StructuralEq for LogicalOperation {}
- #[automatically_derived]
- impl ::core::cmp::Eq for LogicalOperation {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for LogicalOperation {
- #[inline]
- fn cmp(&self, other: &LogicalOperation) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for LogicalOperation {
- #[inline]
- fn partial_cmp(
- &self,
- other: &LogicalOperation,
- ) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralPartialEq for LogicalOperation {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for LogicalOperation {
- #[inline]
- fn eq(&self, other: &LogicalOperation) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- impl TryFrom<TokenKind> for LogicalOperation {
- type Error = ();
- fn try_from(kind: TokenKind) -> Result<Self, Self::Error> {
- match kind {
- TokenKind::DoubleAmpersand => Ok(Self::And),
- TokenKind::DoublePipe => Ok(Self::Or),
- TokenKind::DoubleEqual => Ok(Self::Equals),
- TokenKind::ExclamationEq => Ok(Self::NotEquals),
- TokenKind::RightAngle => Ok(Self::GreaterThan),
- TokenKind::RightAngleEq => Ok(Self::GreaterThanOrEquals),
- TokenKind::LeftAngle => Ok(Self::LessThan),
- TokenKind::LeftAngleEq => Ok(Self::LessThanOrEquals),
- _ => Err(()),
- }
- }
- }
- pub struct BinaryExpr {
- pub lhs: ExprContainer,
- pub op: BinaryOperation,
- pub rhs: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for BinaryExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "BinaryExpr",
- "lhs",
- &&self.lhs,
- "op",
- &&self.op,
- "rhs",
- &&self.rhs,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for BinaryExpr {
- #[inline]
- fn clone(&self) -> BinaryExpr {
- BinaryExpr {
- lhs: ::core::clone::Clone::clone(&self.lhs),
- op: ::core::clone::Clone::clone(&self.op),
- rhs: ::core::clone::Clone::clone(&self.rhs),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for BinaryExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for BinaryExpr {
- #[inline]
- fn eq(&self, other: &BinaryExpr) -> bool {
- self.lhs == other.lhs && self.op == other.op && self.rhs == other.rhs
- }
- #[inline]
- fn ne(&self, other: &BinaryExpr) -> bool {
- self.lhs != other.lhs || self.op != other.op || self.rhs != other.rhs
- }
- }
- pub enum BinaryOperation {
- Plus,
- Minus,
- Multiply,
- Divide,
- Modulus,
- And,
- Or,
- Xor,
- LeftShift,
- RightShift,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for BinaryOperation {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- BinaryOperation::Plus => ::core::fmt::Formatter::write_str(f, "Plus"),
- BinaryOperation::Minus => ::core::fmt::Formatter::write_str(f, "Minus"),
- BinaryOperation::Multiply => ::core::fmt::Formatter::write_str(f, "Multiply"),
- BinaryOperation::Divide => ::core::fmt::Formatter::write_str(f, "Divide"),
- BinaryOperation::Modulus => ::core::fmt::Formatter::write_str(f, "Modulus"),
- BinaryOperation::And => ::core::fmt::Formatter::write_str(f, "And"),
- BinaryOperation::Or => ::core::fmt::Formatter::write_str(f, "Or"),
- BinaryOperation::Xor => ::core::fmt::Formatter::write_str(f, "Xor"),
- BinaryOperation::LeftShift => ::core::fmt::Formatter::write_str(f, "LeftShift"),
- BinaryOperation::RightShift => ::core::fmt::Formatter::write_str(f, "RightShift"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for BinaryOperation {
- #[inline]
- fn clone(&self) -> BinaryOperation {
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for BinaryOperation {}
- impl ::core::marker::StructuralEq for BinaryOperation {}
- #[automatically_derived]
- impl ::core::cmp::Eq for BinaryOperation {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for BinaryOperation {
- #[inline]
- fn cmp(&self, other: &BinaryOperation) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for BinaryOperation {
- #[inline]
- fn partial_cmp(
- &self,
- other: &BinaryOperation,
- ) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralPartialEq for BinaryOperation {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for BinaryOperation {
- #[inline]
- fn eq(&self, other: &BinaryOperation) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- impl TryFrom<TokenKind> for BinaryOperation {
- type Error = ();
- fn try_from(value: TokenKind) -> Result<Self, Self::Error> {
- match value {
- TokenKind::Plus => Ok(Self::Plus),
- TokenKind::Minus => Ok(Self::Minus),
- TokenKind::Asterisk => Ok(Self::Multiply),
- TokenKind::Slash => Ok(Self::Divide),
- TokenKind::Percent => Ok(Self::Modulus),
- TokenKind::Ampersand => Ok(Self::And),
- TokenKind::Pipe => Ok(Self::Or),
- TokenKind::Caret => Ok(Self::Xor),
- TokenKind::DoubleLeftAngle => Ok(Self::LeftShift),
- TokenKind::DoubleRightAngle => Ok(Self::RightShift),
- _ => Err(()),
- }
- }
- }
- pub struct UnaryExpr {
- pub op: UnaryOperation,
- pub expr: ExprContainer,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for UnaryExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "UnaryExpr",
- "op",
- &&self.op,
- "expr",
- &&self.expr,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for UnaryExpr {
- #[inline]
- fn clone(&self) -> UnaryExpr {
- UnaryExpr {
- op: ::core::clone::Clone::clone(&self.op),
- expr: ::core::clone::Clone::clone(&self.expr),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for UnaryExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for UnaryExpr {
- #[inline]
- fn eq(&self, other: &UnaryExpr) -> bool {
- self.op == other.op && self.expr == other.expr
- }
- #[inline]
- fn ne(&self, other: &UnaryExpr) -> bool {
- self.op != other.op || self.expr != other.expr
- }
- }
- pub enum UnaryOperation {
- Not,
- Negate,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for UnaryOperation {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- UnaryOperation::Not => ::core::fmt::Formatter::write_str(f, "Not"),
- UnaryOperation::Negate => ::core::fmt::Formatter::write_str(f, "Negate"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for UnaryOperation {
- #[inline]
- fn clone(&self) -> UnaryOperation {
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for UnaryOperation {}
- impl ::core::marker::StructuralEq for UnaryOperation {}
- #[automatically_derived]
- impl ::core::cmp::Eq for UnaryOperation {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for UnaryOperation {
- #[inline]
- fn cmp(&self, other: &UnaryOperation) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for UnaryOperation {
- #[inline]
- fn partial_cmp(
- &self,
- other: &UnaryOperation,
- ) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralPartialEq for UnaryOperation {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for UnaryOperation {
- #[inline]
- fn eq(&self, other: &UnaryOperation) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- impl TryFrom<TokenKind> for UnaryOperation {
- type Error = ();
- fn try_from(value: TokenKind) -> Result<Self, Self::Error> {
- match value {
- TokenKind::Exclamation => Ok(Self::Not),
- TokenKind::Minus => Ok(Self::Negate),
- _ => Err(()),
- }
- }
- }
- pub struct CallExpr {
- pub callee: ExprContainer,
- pub args: Vec<ExprContainer>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for CallExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "CallExpr",
- "callee",
- &&self.callee,
- "args",
- &&self.args,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for CallExpr {
- #[inline]
- fn clone(&self) -> CallExpr {
- CallExpr {
- callee: ::core::clone::Clone::clone(&self.callee),
- args: ::core::clone::Clone::clone(&self.args),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for CallExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for CallExpr {
- #[inline]
- fn eq(&self, other: &CallExpr) -> bool {
- self.callee == other.callee && self.args == other.args
- }
- #[inline]
- fn ne(&self, other: &CallExpr) -> bool {
- self.callee != other.callee || self.args != other.args
- }
- }
- pub struct NumberExpr {
- pub value: InternedString,
- pub kind: NumberKind,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for NumberExpr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "NumberExpr",
- "value",
- &&self.value,
- "kind",
- &&self.kind,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for NumberExpr {
- #[inline]
- fn clone(&self) -> NumberExpr {
- NumberExpr {
- value: ::core::clone::Clone::clone(&self.value),
- kind: ::core::clone::Clone::clone(&self.kind),
- }
- }
- }
- impl ::core::marker::StructuralPartialEq for NumberExpr {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for NumberExpr {
- #[inline]
- fn eq(&self, other: &NumberExpr) -> bool {
- self.value == other.value && self.kind == other.kind
- }
- #[inline]
- fn ne(&self, other: &NumberExpr) -> bool {
- self.value != other.value || self.kind != other.kind
- }
- }
- }
- mod diagnostics {
- use crate::memory::ValueAddr;
- use owo_colors::OwoColorize;
- use std::cmp::max;
- use std::fmt::{Display, Formatter};
- pub struct Diagnostic {
- pub span: Span,
- pub message: String,
- pub severity: Severity,
- pub code: ErrorCode,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Diagnostic {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field4_finish(
- f,
- "Diagnostic",
- "span",
- &&self.span,
- "message",
- &&self.message,
- "severity",
- &&self.severity,
- "code",
- &&self.code,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Diagnostic {
- #[inline]
- fn clone(&self) -> Diagnostic {
- Diagnostic {
- span: ::core::clone::Clone::clone(&self.span),
- message: ::core::clone::Clone::clone(&self.message),
- severity: ::core::clone::Clone::clone(&self.severity),
- code: ::core::clone::Clone::clone(&self.code),
- }
- }
- }
- struct Pos {
- line: usize,
- column: usize,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Pos {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "Pos",
- "line",
- &&self.line,
- "column",
- &&self.column,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for Pos {
- #[inline]
- fn clone(&self) -> Pos {
- let _: ::core::clone::AssertParamIsClone<usize>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Pos {}
- #[automatically_derived]
- impl ::core::cmp::Ord for Pos {
- #[inline]
- fn cmp(&self, other: &Pos) -> ::core::cmp::Ordering {
- match ::core::cmp::Ord::cmp(&self.line, &other.line) {
- ::core::cmp::Ordering::Equal => ::core::cmp::Ord::cmp(&self.column, &other.column),
- cmp => cmp,
- }
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for Pos {
- #[inline]
- fn partial_cmp(&self, other: &Pos) -> ::core::option::Option<::core::cmp::Ordering> {
- match ::core::cmp::PartialOrd::partial_cmp(&self.line, &other.line) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
- ::core::cmp::PartialOrd::partial_cmp(&self.column, &other.column)
- }
- cmp => cmp,
- }
- }
- }
- impl ::core::marker::StructuralEq for Pos {}
- #[automatically_derived]
- impl ::core::cmp::Eq for Pos {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<usize>;
- }
- }
- impl ::core::marker::StructuralPartialEq for Pos {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Pos {
- #[inline]
- fn eq(&self, other: &Pos) -> bool {
- self.line == other.line && self.column == other.column
- }
- #[inline]
- fn ne(&self, other: &Pos) -> bool {
- self.line != other.line || self.column != other.column
- }
- }
- impl Diagnostic {
- fn calculate_pos_for_n(&self, file: &str, n: usize) -> Pos {
- let mut line = 1;
- let mut column = 1;
- for (idx, ch) in file.chars().enumerate() {
- if idx == n {
- break;
- }
- if ch == '\n' {
- line += 1;
- column = 1;
- } else {
- column += 1;
- }
- }
- Pos { line, column }
- }
- fn max_line_number_size(pos1: Pos, pos2: Pos) -> usize {
- max(pos1.line.literal_size(), pos2.line.literal_size())
- }
- fn generate_line(
- buf: &mut String,
- line: &str,
- line_number: usize,
- max_line_number_size: usize,
- ) {
- buf.push_str(&{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", " ", "\n"],
- &[
- ::core::fmt::ArgumentV1::new_display(
- &{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", "", "|"],
- &[
- ::core::fmt::ArgumentV1::new_display(&line_number),
- ::core::fmt::ArgumentV1::new_display(&" ".repeat(
- max_line_number_size - line_number.literal_size() + 1,
- )),
- ],
- ));
- res
- }
- .bright_blue()
- .bold(),
- ),
- ::core::fmt::ArgumentV1::new_display(&line),
- ],
- ));
- res
- });
- }
- fn write_marker(buf: &mut String, blank_line: &str, padding: usize, count: usize) {
- if count == 0 {
- return;
- }
- buf.push_str(&{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", "", "", "\n"],
- &[
- ::core::fmt::ArgumentV1::new_display(&blank_line),
- ::core::fmt::ArgumentV1::new_display(&" ".repeat(padding - 1)),
- ::core::fmt::ArgumentV1::new_display(
- &"^".repeat(count).bright_yellow().bold(),
- ),
- ],
- ));
- res
- });
- }
- fn write_pos(
- &self,
- buf: &mut String,
- lines: &[&str],
- blank_line: &str,
- starting_pos: Pos,
- ending_pos: Pos,
- max_line_num_size: usize,
- print_trailing_empty_line: bool,
- ) {
- for line_num in starting_pos.line..ending_pos.line + 1 {
- let line = lines[line_num - 1].replace('\t', " ");
- if !print_trailing_empty_line && line_num == ending_pos.line && line.is_empty() {
- break;
- }
- let tab_count = count_tab_until(lines[line_num - 1], starting_pos.column);
- let padding = if line_num == starting_pos.line {
- (starting_pos.column + tab_count * 4)
- .checked_sub(tab_count)
- .unwrap_or_default()
- } else {
- 0
- };
- let count;
- if starting_pos.line == ending_pos.line {
- if starting_pos.column == ending_pos.column {
- count = 1;
- } else {
- let tab_count_until_end =
- tab_count - count_tab_until(lines[line_num - 1], ending_pos.column);
- count =
- (ending_pos.column - starting_pos.column) + 1 + 4 * tab_count_until_end
- - tab_count_until_end;
- }
- } else if line_num == starting_pos.line {
- count = line.len() - padding;
- } else if line_num == ending_pos.line {
- let tab_count_until_end =
- count_tab_until(lines[line_num - 1], ending_pos.column);
- count = ending_pos.column + 1 + tab_count_until_end * 4 - tab_count_until_end;
- } else {
- count = line.len() - padding;
- }
- Self::generate_line(buf, &line, line_num, max_line_num_size);
- Self::write_marker(buf, blank_line, padding + 1, count);
- }
- }
- fn pos_to_string(pos1: Pos, pos2: Pos) -> String {
- if pos1 == pos2 {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", ":"],
- &[
- ::core::fmt::ArgumentV1::new_display(&pos1.line),
- ::core::fmt::ArgumentV1::new_display(&pos1.column),
- ],
- ));
- res
- }
- } else {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", ":", "-", ":"],
- &[
- ::core::fmt::ArgumentV1::new_display(&pos1.line),
- ::core::fmt::ArgumentV1::new_display(&pos1.column),
- ::core::fmt::ArgumentV1::new_display(&pos2.line),
- ::core::fmt::ArgumentV1::new_display(&pos2.column),
- ],
- ));
- res
- }
- }
- }
- pub fn display(&self, file_name: &str, file_content: &str) -> String {
- let mut buf = String::new();
- let lines = file_content.split('\n').collect::<Vec<&str>>();
- let starting_pos = self.calculate_pos_for_n(file_content, self.span.lo);
- let ending_pos = self.calculate_pos_for_n(file_content, self.span.hi);
- let max_line_num_size = Self::max_line_number_size(starting_pos, ending_pos);
- let blank_line = {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", " |"],
- &[::core::fmt::ArgumentV1::new_display(
- &" ".repeat(max_line_num_size),
- )],
- ));
- res
- }
- .bright_blue()
- .bold()
- .to_string();
- let blank_line_with_newline = blank_line.clone() + "\n";
- buf.push_str(&{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", ": ", "\n"],
- &[
- ::core::fmt::ArgumentV1::new_display(
- &if self.severity == Severity::Error {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", "[", "]"],
- &[
- ::core::fmt::ArgumentV1::new_display(&"error"),
- ::core::fmt::ArgumentV1::new_display(&self.code),
- ],
- ));
- res
- }
- .bright_red()
- .bold()
- .to_string()
- } else if self.severity == Severity::Warning {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", "[", "]"],
- &[
- ::core::fmt::ArgumentV1::new_display(&"warning"),
- ::core::fmt::ArgumentV1::new_display(&self.code),
- ],
- ));
- res
- }
- .bright_yellow()
- .bold()
- .to_string()
- } else {
- "info".to_string().bright_blue().bold().to_string()
- },
- ),
- ::core::fmt::ArgumentV1::new_display(&self.message),
- ],
- ));
- res
- });
- buf.push_str(&{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["", "", " ", ":", "\n"],
- &[
- ::core::fmt::ArgumentV1::new_display(&" ".repeat(max_line_num_size)),
- ::core::fmt::ArgumentV1::new_display(&"-->".bright_blue().bold()),
- ::core::fmt::ArgumentV1::new_display(&file_name),
- ::core::fmt::ArgumentV1::new_display(&Self::pos_to_string(
- starting_pos,
- ending_pos,
- )),
- ],
- ));
- res
- });
- buf.push_str(&blank_line_with_newline);
- self.write_pos(
- &mut buf,
- &lines,
- &blank_line,
- starting_pos,
- ending_pos,
- max_line_num_size,
- true,
- );
- buf.push_str(&blank_line_with_newline);
- buf.push_str(
- &{
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &[
- "For more information about this error, try `",
- " explain ",
- "`\n",
- ],
- &[
- ::core::fmt::ArgumentV1::new_display(&std::env::args().next().unwrap()),
- ::core::fmt::ArgumentV1::new_display(&self.code),
- ],
- ));
- res
- }
- .bold()
- .to_string(),
- );
- buf
- }
- }
- fn count_tab_until(line: &str, offset: usize) -> usize {
- let mut count = 0;
- for (idx, ch) in line.chars().enumerate() {
- if ch == '\t' {
- count += 1;
- }
- if idx == offset {
- break;
- }
- }
- count
- }
- pub enum ErrorCode {
- UnknownToken,
- InvalidNumber,
- UnterminatedString,
- UnexpectedToken,
- InvalidAssignment,
- InvalidLoopControl,
- UndefinedVariable,
- UndefinedFunction,
- InvalidBinaryOperation,
- InvalidUnaryOperation,
- InvalidEscapeCharacter,
- InvalidType,
- ArityError,
- Return(ValueAddr),
- InvalidDataPropertySet,
- MissingProp,
- UnknownProp,
- MutabilityError,
- Break,
- Continue,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for ErrorCode {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- ErrorCode::UnknownToken => ::core::fmt::Formatter::write_str(f, "UnknownToken"),
- ErrorCode::InvalidNumber => ::core::fmt::Formatter::write_str(f, "InvalidNumber"),
- ErrorCode::UnterminatedString => {
- ::core::fmt::Formatter::write_str(f, "UnterminatedString")
- }
- ErrorCode::UnexpectedToken => {
- ::core::fmt::Formatter::write_str(f, "UnexpectedToken")
- }
- ErrorCode::InvalidAssignment => {
- ::core::fmt::Formatter::write_str(f, "InvalidAssignment")
- }
- ErrorCode::InvalidLoopControl => {
- ::core::fmt::Formatter::write_str(f, "InvalidLoopControl")
- }
- ErrorCode::UndefinedVariable => {
- ::core::fmt::Formatter::write_str(f, "UndefinedVariable")
- }
- ErrorCode::UndefinedFunction => {
- ::core::fmt::Formatter::write_str(f, "UndefinedFunction")
- }
- ErrorCode::InvalidBinaryOperation => {
- ::core::fmt::Formatter::write_str(f, "InvalidBinaryOperation")
- }
- ErrorCode::InvalidUnaryOperation => {
- ::core::fmt::Formatter::write_str(f, "InvalidUnaryOperation")
- }
- ErrorCode::InvalidEscapeCharacter => {
- ::core::fmt::Formatter::write_str(f, "InvalidEscapeCharacter")
- }
- ErrorCode::InvalidType => ::core::fmt::Formatter::write_str(f, "InvalidType"),
- ErrorCode::ArityError => ::core::fmt::Formatter::write_str(f, "ArityError"),
- ErrorCode::Return(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Return", &__self_0)
- }
- ErrorCode::InvalidDataPropertySet => {
- ::core::fmt::Formatter::write_str(f, "InvalidDataPropertySet")
- }
- ErrorCode::MissingProp => ::core::fmt::Formatter::write_str(f, "MissingProp"),
- ErrorCode::UnknownProp => ::core::fmt::Formatter::write_str(f, "UnknownProp"),
- ErrorCode::MutabilityError => {
- ::core::fmt::Formatter::write_str(f, "MutabilityError")
- }
- ErrorCode::Break => ::core::fmt::Formatter::write_str(f, "Break"),
- ErrorCode::Continue => ::core::fmt::Formatter::write_str(f, "Continue"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for ErrorCode {}
- #[automatically_derived]
- impl ::core::clone::Clone for ErrorCode {
- #[inline]
- fn clone(&self) -> ErrorCode {
- let _: ::core::clone::AssertParamIsClone<ValueAddr>;
- *self
- }
- }
- impl Display for ErrorCode {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- ErrorCode::UnknownToken => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0001"], &[]))
- }
- ErrorCode::InvalidNumber => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0002"], &[]))
- }
- ErrorCode::UnterminatedString => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0003"], &[]))
- }
- ErrorCode::UnexpectedToken => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0004"], &[]))
- }
- ErrorCode::InvalidAssignment => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0005"], &[]))
- }
- ErrorCode::InvalidLoopControl => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0006"], &[]))
- }
- ErrorCode::UndefinedVariable => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0007"], &[]))
- }
- ErrorCode::UndefinedFunction => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0008"], &[]))
- }
- ErrorCode::InvalidBinaryOperation => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0009"], &[]))
- }
- ErrorCode::InvalidEscapeCharacter => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0010"], &[]))
- }
- ErrorCode::InvalidUnaryOperation => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0012"], &[]))
- }
- ErrorCode::InvalidType => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0013"], &[]))
- }
- ErrorCode::ArityError => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0014"], &[]))
- }
- ErrorCode::Return(_) => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0000"], &[]))
- }
- ErrorCode::InvalidDataPropertySet => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0015"], &[]))
- }
- ErrorCode::MissingProp => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0016"], &[]))
- }
- ErrorCode::UnknownProp => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0017"], &[]))
- }
- ErrorCode::MutabilityError => {
- f.write_fmt(::core::fmt::Arguments::new_v1(&["E0018"], &[]))
- }
- ErrorCode::Break => f.write_fmt(::core::fmt::Arguments::new_v1(&["E0000"], &[])),
- ErrorCode::Continue => f.write_fmt(::core::fmt::Arguments::new_v1(&["E0000"], &[])),
- }
- }
- }
- pub enum Severity {
- Error,
- Warning,
- Info,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Severity {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Severity::Error => ::core::fmt::Formatter::write_str(f, "Error"),
- Severity::Warning => ::core::fmt::Formatter::write_str(f, "Warning"),
- Severity::Info => ::core::fmt::Formatter::write_str(f, "Info"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Severity {}
- #[automatically_derived]
- impl ::core::clone::Clone for Severity {
- #[inline]
- fn clone(&self) -> Severity {
- *self
- }
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for Severity {
- #[inline]
- fn cmp(&self, other: &Severity) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for Severity {
- #[inline]
- fn partial_cmp(&self, other: &Severity) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralEq for Severity {}
- #[automatically_derived]
- impl ::core::cmp::Eq for Severity {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- impl ::core::marker::StructuralPartialEq for Severity {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Severity {
- #[inline]
- fn eq(&self, other: &Severity) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- impl Display for Severity {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let s = match self {
- Severity::Error => "error",
- Severity::Warning => "warning",
- Severity::Info => "info",
- };
- f.write_fmt(::core::fmt::Arguments::new_v1(
- &[""],
- &[::core::fmt::ArgumentV1::new_display(&s)],
- ))
- }
- }
- pub struct Span {
- pub lo: usize,
- pub hi: usize,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Span {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f, "Span", "lo", &&self.lo, "hi", &&self.hi,
- )
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Span {}
- #[automatically_derived]
- impl ::core::clone::Clone for Span {
- #[inline]
- fn clone(&self) -> Span {
- let _: ::core::clone::AssertParamIsClone<usize>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for Span {
- #[inline]
- fn cmp(&self, other: &Span) -> ::core::cmp::Ordering {
- match ::core::cmp::Ord::cmp(&self.lo, &other.lo) {
- ::core::cmp::Ordering::Equal => ::core::cmp::Ord::cmp(&self.hi, &other.hi),
- cmp => cmp,
- }
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for Span {
- #[inline]
- fn partial_cmp(&self, other: &Span) -> ::core::option::Option<::core::cmp::Ordering> {
- match ::core::cmp::PartialOrd::partial_cmp(&self.lo, &other.lo) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
- ::core::cmp::PartialOrd::partial_cmp(&self.hi, &other.hi)
- }
- cmp => cmp,
- }
- }
- }
- impl ::core::marker::StructuralEq for Span {}
- #[automatically_derived]
- impl ::core::cmp::Eq for Span {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<usize>;
- }
- }
- impl ::core::marker::StructuralPartialEq for Span {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for Span {
- #[inline]
- fn eq(&self, other: &Span) -> bool {
- self.lo == other.lo && self.hi == other.hi
- }
- #[inline]
- fn ne(&self, other: &Span) -> bool {
- self.lo != other.lo || self.hi != other.hi
- }
- }
- impl Span {
- pub fn new(lo: usize, hi: usize) -> Self {
- Self { lo, hi }
- }
- pub fn merge(self, s2: Span) -> Self {
- Self {
- lo: self.lo,
- hi: s2.hi,
- }
- }
- }
- trait LiteralSize {
- fn literal_size(self) -> usize;
- }
- impl LiteralSize for usize {
- fn literal_size(self) -> usize {
- (0..).take_while(|i| 10usize.pow(*i) <= self).count()
- }
- }
- }
- mod interner {
- use parking_lot::RwLock;
- pub struct InternedString(usize);
- #[automatically_derived]
- impl ::core::fmt::Debug for InternedString {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "InternedString", &&self.0)
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for InternedString {}
- #[automatically_derived]
- impl ::core::clone::Clone for InternedString {
- #[inline]
- fn clone(&self) -> InternedString {
- let _: ::core::clone::AssertParamIsClone<usize>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::default::Default for InternedString {
- #[inline]
- fn default() -> InternedString {
- InternedString(::core::default::Default::default())
- }
- }
- impl ::core::marker::StructuralPartialEq for InternedString {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for InternedString {
- #[inline]
- fn eq(&self, other: &InternedString) -> bool {
- self.0 == other.0
- }
- #[inline]
- fn ne(&self, other: &InternedString) -> bool {
- self.0 != other.0
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for InternedString {
- #[inline]
- fn partial_cmp(
- &self,
- other: &InternedString,
- ) -> ::core::option::Option<::core::cmp::Ordering> {
- ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
- }
- }
- impl ::core::marker::StructuralEq for InternedString {}
- #[automatically_derived]
- impl ::core::cmp::Eq for InternedString {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<usize>;
- }
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for InternedString {
- #[inline]
- fn cmp(&self, other: &InternedString) -> ::core::cmp::Ordering {
- ::core::cmp::Ord::cmp(&self.0, &other.0)
- }
- }
- #[automatically_derived]
- impl ::core::hash::Hash for InternedString {
- fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
- ::core::hash::Hash::hash(&self.0, state)
- }
- }
- pub struct InternedValue(usize);
- #[automatically_derived]
- impl ::core::fmt::Debug for InternedValue {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "InternedValue", &&self.0)
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for InternedValue {}
- #[automatically_derived]
- impl ::core::clone::Clone for InternedValue {
- #[inline]
- fn clone(&self) -> InternedValue {
- let _: ::core::clone::AssertParamIsClone<usize>;
- *self
- }
- }
- impl ::core::marker::StructuralPartialEq for InternedValue {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for InternedValue {
- #[inline]
- fn eq(&self, other: &InternedValue) -> bool {
- self.0 == other.0
- }
- #[inline]
- fn ne(&self, other: &InternedValue) -> bool {
- self.0 != other.0
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for InternedValue {
- #[inline]
- fn partial_cmp(
- &self,
- other: &InternedValue,
- ) -> ::core::option::Option<::core::cmp::Ordering> {
- ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
- }
- }
- impl ::core::marker::StructuralEq for InternedValue {}
- #[automatically_derived]
- impl ::core::cmp::Eq for InternedValue {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<usize>;
- }
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for InternedValue {
- #[inline]
- fn cmp(&self, other: &InternedValue) -> ::core::cmp::Ordering {
- ::core::cmp::Ord::cmp(&self.0, &other.0)
- }
- }
- pub static INTERNER: RwLock<Interner> = RwLock::new(Interner::new());
- pub struct Interner {
- strings: Vec<String>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Interner {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field1_finish(
- f,
- "Interner",
- "strings",
- &&self.strings,
- )
- }
- }
- impl Interner {
- pub const fn new() -> Self {
- Self {
- strings: Vec::new(),
- }
- }
- pub fn intern_string(&mut self, string: String) -> InternedString {
- for (idx, interned_string) in self.strings.iter().enumerate() {
- if interned_string == &string {
- return InternedString(idx);
- }
- }
- let id = self.strings.len();
- self.strings.push(string);
- InternedString(id)
- }
- pub fn get_interned_string(&self, id: InternedString) -> &str {
- &self.strings[id.0]
- }
- }
- }
- mod interp {
- use crate::ast::{
- BinaryOperation, Expr, ExprContainer, FunStmt, LogicalOperation, Mutable, Stmt,
- StmtContainer, UnaryOperation,
- };
- use crate::diagnostics::{Diagnostic, ErrorCode, Severity, Span};
- use crate::interner::{InternedString, INTERNER};
- use crate::lexer::NumberKind;
- use crate::memory::{Allocator, Callable, DataObject, Value, ValueAddr};
- use crate::native::{
- ArrayPopFunction, FloatFunction, InputFunction, IntFunction, PrintFunction,
- PrintlnFunction, SleepFunction,
- };
- use crate::Session;
- use std::cell::RefCell;
- use std::collections::HashMap;
- use std::str::FromStr;
- pub struct Interpreter<'i> {
- allocator: Allocator,
- session: RefCell<&'i mut Session>,
- envs: RefCell<HashMap<InternedString, Vec<Scope>>>,
- current: InternedString,
- context: Vec<InterpreterContext>,
- }
- impl<'i> Interpreter<'i> {
- pub fn new(session: &'i mut Session) -> Self {
- Self {
- allocator: Allocator::new(),
- session: RefCell::new(session),
- envs: RefCell::new(HashMap::new()),
- current: InternedString::default(),
- context: alloc::vec::Vec::new(),
- }
- }
- pub fn init(&mut self) -> bool {
- self.session.borrow_mut().parse_entrypoint();
- let session = self.session.borrow();
- if session.has_diagnostics() {
- session.print_diagnostics();
- return false;
- }
- self.current = session.entry_point;
- let ast = session.get_ast(self.current);
- if let Err(e) = Self::prepare_global_env_for_module(
- self.current,
- ast,
- &self.envs,
- &mut self.allocator,
- ) {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1(
- &["", "\n"],
- &[::core::fmt::ArgumentV1::new_display(&e.display(
- INTERNER.read().get_interned_string(self.current),
- &session.files[&self.current],
- ))],
- ));
- };
- return false;
- };
- if session.debug {
- match &self.envs {
- tmp => {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1_formatted(
- &["[", ":", "] ", " = ", "\n"],
- &match (&"src/interp.rs", &59u32, &"&self.envs", &&tmp) {
- args => [
- ::core::fmt::ArgumentV1::new_display(args.0),
- ::core::fmt::ArgumentV1::new_display(args.1),
- ::core::fmt::ArgumentV1::new_display(args.2),
- ::core::fmt::ArgumentV1::new_debug(args.3),
- ],
- },
- &[
- ::core::fmt::rt::v1::Argument {
- position: 0usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 1usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 2usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 3usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 4u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ],
- unsafe { ::core::fmt::UnsafeArg::new() },
- ));
- };
- tmp
- }
- };
- match ast {
- tmp => {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1_formatted(
- &["[", ":", "] ", " = ", "\n"],
- &match (&"src/interp.rs", &60u32, &"ast", &&tmp) {
- args => [
- ::core::fmt::ArgumentV1::new_display(args.0),
- ::core::fmt::ArgumentV1::new_display(args.1),
- ::core::fmt::ArgumentV1::new_display(args.2),
- ::core::fmt::ArgumentV1::new_debug(args.3),
- ],
- },
- &[
- ::core::fmt::rt::v1::Argument {
- position: 0usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 1usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 2usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 3usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 4u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ],
- unsafe { ::core::fmt::UnsafeArg::new() },
- ));
- };
- tmp
- }
- };
- }
- true
- }
- pub fn interpret(&mut self) {
- let session = self.session.borrow();
- let ast = session.get_ast(self.current).to_vec();
- drop(session);
- if let Err(e) = self.interpret_ast(&ast) {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1(
- &["", "\n"],
- &[::core::fmt::ArgumentV1::new_display(&e.display(
- INTERNER.read().get_interned_string(self.current),
- &self.session.borrow().files[&self.current],
- ))],
- ));
- };
- }
- }
- pub fn interpret_ast(&mut self, ast: &[StmtContainer]) -> Result<(), Diagnostic> {
- for stmt in ast {
- if let Stmt::Fun(fs) = &stmt.stmt {
- if INTERNER.read().get_interned_string(fs.name) != "main" {
- continue;
- }
- }
- self.interpret_stmt(stmt)?;
- }
- Ok(())
- }
- fn interpret_stmt(&mut self, stmt: &StmtContainer) -> Result<(), Diagnostic> {
- match &stmt.stmt {
- Stmt::Var(var_stmt) => {
- let interpreted_value = self.interpret_expr(&var_stmt.value)?;
- let _ = &mut self
- .envs
- .borrow_mut()
- .get_mut(&self.current)
- .unwrap()
- .last_mut()
- .unwrap()
- .insert(
- var_stmt.name,
- EnvItem {
- mutable: var_stmt.mutable,
- addr: interpreted_value,
- },
- );
- }
- Stmt::Fun(fun_stmt) => {
- self.interpret_function(fun_stmt)?;
- }
- Stmt::Loop(block) => loop {
- if let Err(e) = self.interpret_stmt(block) {
- if match e.code {
- ErrorCode::Break => true,
- _ => false,
- } {
- return Ok(());
- } else if !match e.code {
- ErrorCode::Continue => true,
- _ => false,
- } {
- return Err(e);
- }
- }
- },
- Stmt::Block(stmts) => {
- for stmt in stmts {
- self.interpret_stmt(stmt)?;
- }
- }
- Stmt::If(if_stmt) => {
- let condition_addr = self.interpret_expr(&if_stmt.condition)?;
- let condition_container = self.allocator.get(condition_addr);
- let condition_read = condition_container.read();
- let is_condition_met = match &*condition_read {
- Value::None | Value::Boolean(false) => false,
- _ => true,
- };
- if is_condition_met {
- self.interpret_stmt(&if_stmt.block)?;
- } else if let Some(else_) = &if_stmt.else_ {
- self.interpret_stmt(else_)?;
- } else if let Some(then) = &if_stmt.then {
- self.interpret_stmt(then)?;
- }
- return Ok(());
- }
- Stmt::Iter(iter_stmt) => {
- let iterable_addr = self.interpret_expr(&iter_stmt.iterable)?;
- let iterable_container = self.allocator.get(iterable_addr);
- let iterable_read = iterable_container.read();
- let array = match &*iterable_read {
- Value::Array(arr) => arr,
- val => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot iter type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&val.type_())],
- ));
- res
- },
- span: iter_stmt.iterable.span,
- })
- }
- };
- for item in array {
- let mut scope = Scope::new();
- scope.insert(
- iter_stmt.binding,
- EnvItem {
- mutable: Mutable::No,
- addr: *item,
- },
- );
- self.envs
- .borrow_mut()
- .get_mut(&self.current)
- .unwrap()
- .push(scope);
- if let Err(e) = self.interpret_stmt(&iter_stmt.block) {
- if match e.code {
- ErrorCode::Break => true,
- _ => false,
- } {
- return Ok(());
- } else if !match e.code {
- ErrorCode::Continue => true,
- _ => false,
- } {
- return Err(e);
- }
- }
- self.envs.borrow_mut().get_mut(&self.current).unwrap().pop();
- }
- }
- Stmt::Ret(v) => {
- let val_addr = self.interpret_expr(v)?;
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::Return(val_addr),
- message: String::from("This error should never be displayed"),
- span: stmt.span,
- });
- }
- Stmt::Break => {
- return Err(Diagnostic {
- severity: Severity::Warning,
- span: stmt.span,
- message: String::new(),
- code: ErrorCode::Break,
- })
- }
- Stmt::Continue => {
- return Err(Diagnostic {
- severity: Severity::Warning,
- span: stmt.span,
- message: String::new(),
- code: ErrorCode::Continue,
- })
- }
- Stmt::Expr(expr) => {
- self.interpret_expr(expr)?;
- }
- Stmt::Data(_) => (),
- _ => ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["not yet implemented: "],
- &[::core::fmt::ArgumentV1::new_display(
- &::core::fmt::Arguments::new_v1(
- &[""],
- &[::core::fmt::ArgumentV1::new_debug(&stmt)],
- ),
- )],
- )),
- }
- Ok(())
- }
- fn interpret_function(
- &mut self,
- fun_stmt: &FunStmt,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let mut env = self.envs.borrow_mut();
- env.get_mut(&self.current).unwrap().push(HashMap::new());
- drop(env);
- match &fun_stmt.body.stmt {
- Stmt::Block(stmts) => {
- for stmt in stmts {
- if let Err(err) = self.interpret_stmt(stmt) {
- return if let ErrorCode::Return(rv) = err.code {
- Ok(Some(rv))
- } else {
- Err(err)
- };
- }
- }
- }
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- }
- let mut env = self.envs.borrow_mut();
- for _val in env.get_mut(&self.current).unwrap().last().unwrap() {}
- Ok(None)
- }
- fn get_mutability(&self, name: InternedString) -> Option<Mutable> {
- let envs = self.envs.borrow();
- let scopes = envs[&self.current].iter().rev();
- for scope in scopes {
- if let Some(env_item) = scope.get(&name) {
- return Some(env_item.mutable);
- }
- }
- None
- }
- fn interpret_expr(&mut self, expr: &ExprContainer) -> Result<ValueAddr, Diagnostic> {
- let val = match &expr.expr {
- Expr::Assignment(assignment_expr) => {
- let name = match assignment_expr.lvalue.expr {
- Expr::Variable(name) => name,
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- };
- if let Some(mutability) = self.get_mutability(name) {
- if mutability == Mutable::No {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::MutabilityError,
- message: String::from("Attempt to mutate immutable variable"),
- span: expr.span,
- });
- }
- } else {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UndefinedVariable,
- message: String::from("Undefined variable/type"),
- span: expr.span,
- });
- }
- let rvalue = self.interpret_expr(&assignment_expr.rvalue)?;
- let mut envs = self.envs.borrow_mut();
- let scopes = envs.get_mut(&self.current).unwrap().iter_mut().rev();
- for scope in scopes {
- if scope.get_mut(&name).is_some() {
- scope.insert(
- name,
- EnvItem {
- mutable: Mutable::Yes,
- addr: rvalue,
- },
- );
- break;
- }
- }
- return Ok(rvalue);
- }
- Expr::Data(data_expr) => {
- let data_addr = self.interpret_expr(&ExprContainer {
- span: expr.span,
- expr: Expr::Variable(data_expr.name),
- })?;
- let data_container = self.allocator.get(data_addr);
- let data_read = data_container.read();
- let data_stmt = match &*data_read {
- Value::Data(ds, _) => ds,
- val => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Expected data, found type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&val.type_())],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- for prop in &data_stmt.fields {
- if !data_expr.props.contains_key(prop) {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::MissingProp,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Missing property `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(*prop),
- )],
- ));
- res
- },
- span: expr.span,
- });
- }
- }
- for prop in data_expr.props.keys() {
- if !data_stmt.fields.contains(prop) {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UnknownProp,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Unknown property `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(*prop),
- )],
- ));
- res
- },
- span: expr.span,
- });
- }
- }
- let mut values = HashMap::new();
- for (prop, value) in &data_expr.props {
- let value = self.interpret_expr(value)?;
- values.insert(*prop, value);
- }
- Ok(Value::DataObject(DataObject {
- name: data_expr.name,
- values,
- }))
- }
- Expr::Boolean(b) => Ok(Value::Boolean(*b)),
- Expr::Number(ne) => {
- let radix = ne.kind.radix();
- let number = INTERNER.read().get_interned_string(ne.value).to_string();
- match ne.kind {
- NumberKind::DecFloat => match f64::from_str(&number) {
- Ok(v) => Ok(Value::Float(v)),
- Err(e) => Err(Diagnostic {
- span: expr.span,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Failed to parse number: `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&e)],
- ));
- res
- },
- code: ErrorCode::InvalidNumber,
- severity: Severity::Error,
- }),
- },
- _ => match i64::from_str_radix(&number, radix) {
- Ok(v) => Ok(Value::Int(v)),
- Err(e) => Err(Diagnostic {
- span: expr.span,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Failed to parse number: `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&e)],
- ));
- res
- },
- code: ErrorCode::InvalidNumber,
- severity: Severity::Error,
- }),
- },
- }
- }
- Expr::Logical(logical_expr) => {
- let lhs_addr = self.interpret_expr(&logical_expr.lhs)?;
- let lhs_container = self.allocator.get(lhs_addr);
- let lhs_inner = lhs_container.read();
- let rhs_addr = self.interpret_expr(&logical_expr.rhs)?;
- let rhs_container = self.allocator.get(rhs_addr);
- let rhs_inner = rhs_container.read();
- let lhs_type = lhs_inner.type_();
- let rhs_type = rhs_inner.type_();
- let op = logical_expr.op;
- let return_error = move || {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot apply logical operation between `", "` and `", "`"],
- &[
- ::core::fmt::ArgumentV1::new_display(&lhs_type),
- ::core::fmt::ArgumentV1::new_display(&rhs_type),
- ],
- ));
- res
- },
- span: expr.span,
- });
- };
- let res = match (&*lhs_inner, &*rhs_inner) {
- (Value::String(lhs), Value::String(rhs)) => {
- let res;
- {
- let interner = INTERNER.read();
- let lhs_s = interner.get_interned_string(*lhs);
- let rhs_s = interner.get_interned_string(*rhs);
- res = Value::Boolean({
- match op {
- LogicalOperation::GreaterThan => lhs_s.len() > rhs_s.len(),
- LogicalOperation::LessThan => lhs_s.len() < rhs_s.len(),
- LogicalOperation::GreaterThanOrEquals => {
- lhs_s.len() >= rhs_s.len()
- }
- LogicalOperation::LessThanOrEquals => {
- lhs_s.len() <= rhs_s.len()
- }
- LogicalOperation::Equals => lhs_s == rhs_s,
- LogicalOperation::NotEquals => lhs_s != rhs_s,
- LogicalOperation::And => {
- !lhs_s.is_empty() && !rhs_s.is_empty()
- }
- LogicalOperation::Or => {
- !lhs_s.is_empty() || !rhs_s.is_empty()
- }
- }
- });
- }
- res
- }
- (Value::Int(lhs), Value::Float(rhs))
- | (Value::Float(rhs), Value::Int(lhs)) => {
- let lhs = *lhs as f64;
- let rhs = *rhs;
- Value::Boolean(match op {
- LogicalOperation::Equals => lhs == rhs,
- LogicalOperation::NotEquals => lhs != rhs,
- LogicalOperation::GreaterThan => lhs > rhs,
- LogicalOperation::LessThan => lhs < rhs,
- LogicalOperation::GreaterThanOrEquals => lhs >= rhs,
- LogicalOperation::LessThanOrEquals => lhs <= rhs,
- LogicalOperation::And => (lhs != 0.0) && (rhs != 0.0),
- LogicalOperation::Or => (lhs != 0.0) || (rhs != 0.0),
- })
- }
- (Value::Int(lhs), Value::Boolean(rhs))
- | (Value::Boolean(rhs), Value::Int(lhs)) => {
- let lhs = *lhs;
- let rhs = *rhs;
- Value::Boolean(match op {
- LogicalOperation::And => (lhs != 0) && rhs,
- LogicalOperation::Or => (lhs != 0) || rhs,
- _ => return return_error(),
- })
- }
- (Value::Float(lhs), Value::Boolean(rhs))
- | (Value::Boolean(rhs), Value::Float(lhs)) => {
- let lhs = *lhs;
- let rhs = *rhs;
- Value::Boolean(match op {
- LogicalOperation::And => (lhs != 0.0) && rhs,
- LogicalOperation::Or => (lhs != 0.0) || rhs,
- _ => return return_error(),
- })
- }
- (Value::Boolean(lhs), Value::Boolean(rhs)) => {
- let lhs = *lhs;
- let rhs = *rhs;
- Value::Boolean(match op {
- LogicalOperation::And => lhs && rhs,
- LogicalOperation::Or => lhs || rhs,
- _ => return return_error(),
- })
- }
- (Value::Int(lhs), Value::Int(rhs)) => {
- let lhs = *lhs;
- let rhs = *rhs;
- Value::Boolean(match op {
- LogicalOperation::Equals => lhs == rhs,
- LogicalOperation::NotEquals => lhs != rhs,
- LogicalOperation::GreaterThan => lhs > rhs,
- LogicalOperation::LessThan => lhs < rhs,
- LogicalOperation::GreaterThanOrEquals => lhs >= rhs,
- LogicalOperation::LessThanOrEquals => lhs <= rhs,
- LogicalOperation::And => (lhs != 0) && (rhs != 0),
- LogicalOperation::Or => (lhs != 0) || (rhs != 0),
- })
- }
- _ => return return_error(),
- };
- Ok(res)
- }
- Expr::Binary(binary_expr) => {
- let lhs_addr = self.interpret_expr(&binary_expr.lhs)?;
- let lhs_container = self.allocator.get(lhs_addr);
- let lhs_inner = lhs_container.read();
- let rhs_addr = self.interpret_expr(&binary_expr.rhs)?;
- let rhs_container = self.allocator.get(rhs_addr);
- let rhs_inner = rhs_container.read();
- let lhs_type = lhs_inner.type_();
- let rhs_type = rhs_inner.type_();
- let op = binary_expr.op;
- let return_error = move || {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot apply binary operation between `", "` and `", "`"],
- &[
- ::core::fmt::ArgumentV1::new_display(&lhs_type),
- ::core::fmt::ArgumentV1::new_display(&rhs_type),
- ],
- ));
- res
- },
- span: expr.span,
- });
- };
- let res = match (&*lhs_inner, &*rhs_inner) {
- (Value::Int(lhs), Value::Float(rhs))
- | (Value::Float(rhs), Value::Int(lhs)) => match op {
- BinaryOperation::Plus => Value::Float(*lhs as f64 + *rhs),
- BinaryOperation::Minus => Value::Float(*lhs as f64 - *rhs),
- BinaryOperation::Multiply => Value::Float(*lhs as f64 * *rhs),
- BinaryOperation::Divide => Value::Float(*lhs as f64 / *rhs),
- BinaryOperation::Modulus => Value::Float(*lhs as f64 % *rhs),
- _ => return return_error(),
- },
- (Value::Float(lhs), Value::Float(rhs)) => match op {
- BinaryOperation::Plus => Value::Float(*lhs + *rhs),
- BinaryOperation::Minus => Value::Float(*lhs - *rhs),
- BinaryOperation::Multiply => Value::Float(*lhs * *rhs),
- BinaryOperation::Divide => Value::Float(*lhs / *rhs),
- BinaryOperation::Modulus => Value::Float(*lhs % *rhs),
- _ => return return_error(),
- },
- (Value::Int(lhs), Value::Int(rhs)) => match op {
- BinaryOperation::Plus => Value::Int(*lhs + *rhs),
- BinaryOperation::Minus => Value::Int(*lhs - *rhs),
- BinaryOperation::Multiply => Value::Int(*lhs * *rhs),
- BinaryOperation::Divide => Value::Float(*lhs as f64 / *rhs as f64),
- BinaryOperation::Modulus => Value::Int(*lhs % *rhs),
- BinaryOperation::And => Value::Int(*lhs & *rhs),
- BinaryOperation::Or => Value::Int(*lhs | *rhs),
- BinaryOperation::Xor => Value::Int(*lhs ^ *rhs),
- BinaryOperation::LeftShift => Value::Int(*lhs << *rhs),
- BinaryOperation::RightShift => Value::Int(*lhs >> *rhs),
- },
- (Value::String(is), Value::Int(n)) => match op {
- BinaryOperation::Multiply => Value::String({
- let res =
- INTERNER.read().get_interned_string(*is).repeat(*n as usize);
- INTERNER.write().intern_string(res)
- }),
- _ => return return_error(),
- },
- (Value::Array(arr), _) => {
- let mut new_arr = arr.clone();
- new_arr.push(rhs_addr);
- let arr_addr = self.allocator.allocate(Value::Array(new_arr));
- return Ok(arr_addr);
- }
- _ => return return_error(),
- };
- Ok(res)
- }
- Expr::Unary(unary_expr) => {
- let value_addr = self.interpret_expr(&unary_expr.expr)?;
- let value_container = self.allocator.get(value_addr);
- let value_read = value_container.read();
- match unary_expr.op {
- UnaryOperation::Not => match &*value_read {
- Value::None | Value::Boolean(false) => Ok(Value::Boolean(true)),
- _ => Ok(Value::Boolean(false)),
- },
- UnaryOperation::Negate => match &*value_read {
- Value::Int(i) => Ok(Value::Int(-*i)),
- Value::Float(f) => Ok(Value::Float(-*f)),
- v => Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidUnaryOperation,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot apply unary negate to type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&v.type_())],
- ));
- res
- },
- span: expr.span,
- }),
- },
- }
- }
- Expr::Call(call_expr) => {
- let function_addr = self.interpret_expr(&call_expr.callee)?;
- let function_container = self.allocator.get(function_addr);
- let function_read = function_container.read();
- let function = match &*function_read {
- Value::Function(function) => function,
- val => {
- return Err(Diagnostic {
- span: expr.span,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot call type: `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&val.type_())],
- ));
- res
- },
- code: ErrorCode::InvalidType,
- severity: Severity::Error,
- })
- }
- };
- if function.arity() != usize::MAX && call_expr.args.len() > function.arity() {
- return Err(Diagnostic {
- span: expr.span,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Function expects ", " arguments, found ", " arguments"],
- &[
- ::core::fmt::ArgumentV1::new_display(&function.arity()),
- ::core::fmt::ArgumentV1::new_display(&call_expr.args.len()),
- ],
- ));
- res
- },
- code: ErrorCode::ArityError,
- severity: Severity::Error,
- });
- }
- let mut args = alloc::vec::Vec::new();
- for expr in &call_expr.args {
- let val = self.interpret_expr(expr)?;
- args.push(self.allocator.clone(val));
- }
- let res = function.call(self, args);
- if let Ok(v) = res {
- return Ok(v.unwrap_or(self.allocator.get_none()));
- } else if let Err(mut e) = res {
- if e.span
- == (Span {
- lo: usize::MAX,
- hi: usize::MAX,
- })
- {
- e.span = expr.span;
- }
- return Err(e);
- }
- ::core::panicking::panic("internal error: entered unreachable code")
- }
- Expr::None => Ok(Value::None),
- Expr::String(is) => Ok(Value::String(*is)),
- Expr::Grouping(e) => return self.interpret_expr(e),
- Expr::Get(get_expr) => {
- let object_addr = self.interpret_expr(&get_expr.object)?;
- let object_container = self.allocator.get(object_addr);
- let object_read = object_container.read();
- let object = match &*object_read {
- Value::DataObject(dobj) => dobj,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property from type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &object_read.type_(),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- if let Some(value) = object.values.get(&get_expr.property) {
- return Ok(*value);
- } else {
- Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(get_expr.property),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- }
- Expr::Array(array) => {
- let mut items = alloc::vec::Vec::new();
- for expr in array {
- let value = self.interpret_expr(expr)?;
- items.push(value);
- }
- Ok(Value::Array(items))
- }
- Expr::Index(index_expr) => {
- let array_addr = self.interpret_expr(&index_expr.object)?;
- let array_container = self.allocator.get(array_addr);
- let array_read = array_container.read();
- let array = match &*array_read {
- Value::Array(a) => a,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot index type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &array_read.type_(),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- let index_addr = self.interpret_expr(&index_expr.index)?;
- let index = match &*self.allocator.get(index_addr).read() {
- Value::Int(idx) => *idx,
- ty => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot index using type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&ty.type_())],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- return if let Some(val_addr) = array.get(index as usize) {
- Ok(*val_addr)
- } else {
- Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: String::from("Out of bound read"),
- span: expr.span,
- })
- };
- }
- Expr::IndexSet(indexset_expr) => {
- let index_expr = match &indexset_expr.object.expr {
- Expr::Index(index_expr) => index_expr,
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- };
- let array_addr = self.interpret_expr(&index_expr.object)?;
- let array_container = self.allocator.get(array_addr);
- let index_addr = self.interpret_expr(&index_expr.index)?;
- let index = match &*self.allocator.get(index_addr).read() {
- Value::Int(idx) => *idx,
- ty => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot index using type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&ty.type_())],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- let value_addr = self.interpret_expr(&indexset_expr.value)?;
- let mut array_write = array_container.write();
- let array = match &mut *array_write {
- Value::Array(a) => a,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot index type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &array_write.type_(),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- if array.get(index as usize).is_none() {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: String::from("Out of bound read"),
- span: expr.span,
- });
- };
- array[index as usize] = value_addr;
- return Ok(value_addr);
- }
- Expr::Set(set_expr) => {
- if let Expr::Get(get_expr) = &set_expr.object.expr {
- let value = self.interpret_expr(&set_expr.value)?;
- let obj_addr = self.interpret_expr(&get_expr.object)?;
- let obj_container = self.allocator.get(obj_addr);
- let mut obj_write = obj_container.write();
- let data_object = match &mut *obj_write {
- Value::DataObject(data_object) => data_object,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res =
- alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access properties of type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &obj_write.type_(),
- )],
- ));
- res
- },
- span: set_expr.object.span,
- })
- }
- };
- if let std::collections::hash_map::Entry::Occupied(mut e) =
- data_object.values.entry(get_expr.property)
- {
- e.insert(value);
- } else {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(get_expr.property),
- )],
- ));
- res
- },
- span: set_expr.object.span,
- });
- }
- return Ok(obj_addr);
- }
- let object_addr = self.interpret_expr(&set_expr.object)?;
- let value_addr = self.interpret_expr(&set_expr.value)?;
- let object_container = self.allocator.get(object_addr);
- let object_read = object_container.read();
- let object = match &*object_read {
- Value::DataObject(dobj) => dobj,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property from type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &object_read.type_(),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- if object.values.get(&set_expr.property).is_none() {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(set_expr.property),
- )],
- ));
- res
- },
- span: expr.span,
- });
- };
- drop(object_read);
- let mut object_write = object_container.write();
- let object = match &mut *object_write {
- Value::DataObject(dobj) => dobj,
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Cannot access property from type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(
- &object_write.type_(),
- )],
- ));
- res
- },
- span: expr.span,
- })
- }
- };
- object.values.insert(set_expr.property, value_addr);
- return Ok(object_addr);
- }
- Expr::Variable(name) => {
- let envs = self.envs.borrow_mut();
- let scopes = envs[&self.current].iter().rev();
- for scope in scopes {
- if let Some(env_item) = scope.get(name) {
- return Ok(env_item.addr);
- }
- }
- Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UndefinedVariable,
- message: String::from("Undefined variable/type"),
- span: expr.span,
- })
- }
- };
- Ok(self.allocator.allocate(val?))
- }
- pub fn prepare_global_env_for_module(
- name: InternedString,
- ast: &[StmtContainer],
- interpreter_env: &RefCell<HashMap<InternedString, Vec<Scope>>>,
- allocator: &mut Allocator,
- ) -> Result<(), Diagnostic> {
- let mut env = alloc::vec::Vec::new();
- let mut scope = Scope::new();
- let mut create_native_fn =
- |allocator: &mut Allocator, name: &str, function: Box<dyn Callable>| -> EnvItem {
- let env_item = EnvItem {
- mutable: Mutable::No,
- addr: allocator.allocate(Value::Function(function)),
- };
- scope.insert(INTERNER.write().intern_string(name.to_string()), env_item);
- env_item
- };
- create_native_fn(allocator, "print", Box::new(PrintFunction {}));
- create_native_fn(allocator, "println", Box::new(PrintlnFunction {}));
- create_native_fn(allocator, "sleep", Box::new(SleepFunction {}));
- create_native_fn(allocator, "pop", Box::new(ArrayPopFunction {}));
- create_native_fn(allocator, "input", Box::new(InputFunction {}));
- create_native_fn(allocator, "int", Box::new(IntFunction {}));
- create_native_fn(allocator, "float", Box::new(FloatFunction {}));
- for stmt in ast {
- match &stmt.stmt {
- Stmt::Fun(fun_stmt) => {
- scope.insert(
- fun_stmt.name,
- EnvItem {
- mutable: Mutable::No,
- addr: allocator.allocate(Value::Function(Box::new(YalFunction {
- fun_stmt: fun_stmt.clone(),
- }))),
- },
- );
- }
- Stmt::Data(data_stmt) => {
- let value_addr =
- allocator.allocate(Value::Data(data_stmt.clone(), HashMap::new()));
- scope.insert(
- data_stmt.name,
- EnvItem {
- mutable: Mutable::No,
- addr: value_addr,
- },
- );
- }
- Stmt::Methods(methods_stmt) => {
- let data_container = match scope.get(&methods_stmt.data) {
- Some(ei) => allocator.get(ei.addr),
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- span: stmt.span,
- message: String::from("Cannot bind methods to invalid type"),
- })
- }
- };
- let mut data = data_container.write();
- let data_methods = match &mut *data {
- Value::Data(_, methods) => methods,
- _ => {
- ::core::panicking::panic("internal error: entered unreachable code")
- }
- };
- for method in methods_stmt.methods.clone() {
- match method.stmt {
- Stmt::Fun(fun) => {
- data_methods.insert(fun.name, fun);
- }
- _ => ::core::panicking::panic(
- "internal error: entered unreachable code",
- ),
- }
- }
- }
- _ => (),
- }
- }
- env.push(scope);
- interpreter_env.borrow_mut().insert(name, env);
- Ok(())
- }
- pub fn get_allocator_mut(&mut self) -> &mut Allocator {
- &mut self.allocator
- }
- pub fn get_allocator(&self) -> &Allocator {
- &self.allocator
- }
- }
- struct YalFunction {
- fun_stmt: Box<FunStmt>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for YalFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field1_finish(
- f,
- "YalFunction",
- "fun_stmt",
- &&self.fun_stmt,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for YalFunction {
- #[inline]
- fn clone(&self) -> YalFunction {
- YalFunction {
- fun_stmt: ::core::clone::Clone::clone(&self.fun_stmt),
- }
- }
- }
- impl Callable for YalFunction {
- fn arity(&self) -> usize {
- self.fun_stmt.arguments.len()
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let mut env = interpreter.envs.borrow_mut();
- let mut scope = HashMap::new();
- for (k, v) in self.fun_stmt.arguments.iter().zip(args.iter()) {
- scope.insert(
- *k,
- EnvItem {
- addr: *v,
- mutable: Mutable::No,
- },
- );
- }
- let parent_scope;
- if env.get_mut(&interpreter.current).unwrap().len() > 1 {
- parent_scope = env.get_mut(&interpreter.current).unwrap().pop();
- } else {
- parent_scope = None;
- }
- env.get_mut(&interpreter.current).unwrap().push(scope);
- drop(env);
- match &self.fun_stmt.body.stmt {
- Stmt::Block(stmts) => {
- for stmt in stmts {
- if let Err(err) = interpreter.interpret_stmt(stmt) {
- return if let ErrorCode::Return(rv) = err.code {
- let mut env = interpreter.envs.borrow_mut();
- for _val in
- env.get_mut(&interpreter.current).unwrap().last().unwrap()
- {
- }
- env.get_mut(&interpreter.current).unwrap().pop();
- if let Some(parent_scope) = parent_scope {
- env.get_mut(&interpreter.current)
- .unwrap()
- .push(parent_scope);
- }
- Ok(Some(rv))
- } else {
- Err(err)
- };
- }
- }
- }
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- }
- let mut env = interpreter.envs.borrow_mut();
- for _val in env.get_mut(&interpreter.current).unwrap().last().unwrap() {}
- env.get_mut(&interpreter.current).unwrap().pop();
- if let Some(parent_scope) = parent_scope {
- env.get_mut(&interpreter.current)
- .unwrap()
- .push(parent_scope);
- }
- Ok(None)
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<function ", " at ", ">"],
- &[
- ::core::fmt::ArgumentV1::new_display(
- &INTERNER.read().get_interned_string(self.fun_stmt.name),
- ),
- ::core::fmt::ArgumentV1::new_pointer(&(self as *const _)),
- ],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- type Scope = HashMap<InternedString, EnvItem>;
- enum InterpreterContext {
- Function,
- Loop,
- Method,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for InterpreterContext {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- InterpreterContext::Function => ::core::fmt::Formatter::write_str(f, "Function"),
- InterpreterContext::Loop => ::core::fmt::Formatter::write_str(f, "Loop"),
- InterpreterContext::Method => ::core::fmt::Formatter::write_str(f, "Method"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for InterpreterContext {
- #[inline]
- fn clone(&self) -> InterpreterContext {
- match self {
- InterpreterContext::Function => InterpreterContext::Function,
- InterpreterContext::Loop => InterpreterContext::Loop,
- InterpreterContext::Method => InterpreterContext::Method,
- }
- }
- }
- pub struct EnvItem {
- pub mutable: Mutable,
- pub addr: ValueAddr,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for EnvItem {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "EnvItem",
- "mutable",
- &&self.mutable,
- "addr",
- &&self.addr,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for EnvItem {
- #[inline]
- fn clone(&self) -> EnvItem {
- let _: ::core::clone::AssertParamIsClone<Mutable>;
- let _: ::core::clone::AssertParamIsClone<ValueAddr>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for EnvItem {}
- }
- mod lexer {
- use crate::diagnostics::{Diagnostic, ErrorCode, Severity, Span};
- use crate::interner::{InternedString, INTERNER};
- use std::str::Chars;
- pub struct Lexer<'l> {
- source_chars: Chars<'l>,
- source_len: usize,
- pos: usize,
- }
- #[automatically_derived]
- impl<'l> ::core::fmt::Debug for Lexer<'l> {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "Lexer",
- "source_chars",
- &&self.source_chars,
- "source_len",
- &&self.source_len,
- "pos",
- &&self.pos,
- )
- }
- }
- impl<'l> Lexer<'l> {
- pub fn new(source: &'l str) -> Self {
- Self {
- source_chars: source.chars(),
- source_len: source.len(),
- pos: 0,
- }
- }
- fn lex_identifier(&mut self) -> Result<Token, Diagnostic> {
- let start = self.pos;
- let mut end = self.pos;
- let mut ident = String::new();
- ident.push(self.get_current());
- self.advance();
- while !self.is_eof() {
- let c = self.get_current();
- if c.is_alphanumeric() || c == '_' {
- ident.push(c);
- end += 1;
- self.advance();
- } else {
- break;
- }
- }
- let kind = match ident.as_str() {
- "as" => TokenKind::As,
- "const" => TokenKind::Const,
- "mut" => TokenKind::Mut,
- "fun" => TokenKind::Fun,
- "data" => TokenKind::Data,
- "methods" => TokenKind::Methods,
- "true" => TokenKind::True,
- "false" => TokenKind::False,
- "none" => TokenKind::None,
- "loop" => TokenKind::Loop,
- "iter" => TokenKind::Iter,
- "ret" => TokenKind::Ret,
- "continue" => TokenKind::Continue,
- "break" => TokenKind::Break,
- "if" => TokenKind::If,
- "else" => TokenKind::Else,
- _ => TokenKind::Identifier,
- };
- let value = if kind == TokenKind::Identifier {
- TokenValue::String(INTERNER.write().intern_string(ident))
- } else {
- TokenValue::None
- };
- Ok(Token {
- value,
- kind,
- span: Span::new(start, end),
- })
- }
- fn lex_decimal_number(&mut self) -> Result<Token, Diagnostic> {
- let start = self.pos;
- let mut end = self.pos;
- let mut number = String::new();
- number.push(self.get_current());
- self.advance();
- while !self.is_eof() {
- let c = self.get_current();
- if c.is_numeric() || c == '.' {
- number.push(c);
- end += 1;
- self.advance();
- } else {
- break;
- }
- }
- let dot_count = number.matches('.').count();
- if dot_count > 1 {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidNumber,
- message: "Invalid number".to_string(),
- span: Span::new(start, end),
- });
- }
- let number = INTERNER.write().intern_string(number);
- Ok(Token {
- value: TokenValue::Number {
- value: number,
- kind: if dot_count == 1 {
- NumberKind::DecFloat
- } else {
- NumberKind::DecInt
- },
- },
- kind: TokenKind::Number,
- span: Span::new(start, end),
- })
- }
- fn lex_hex_number(&mut self) -> Result<Token, Diagnostic> {
- self.advance();
- self.advance();
- let start = self.pos;
- let mut end = self.pos;
- let mut number = String::new();
- number.push(self.get_current());
- self.advance();
- while !self.is_eof() {
- let c = self.get_current();
- if c.is_numeric() || "ABCDEFabcdef".contains(c) {
- number.push(c);
- end += 1;
- self.advance();
- } else {
- break;
- }
- }
- let number = INTERNER.write().intern_string(number);
- Ok(Token {
- value: TokenValue::Number {
- value: number,
- kind: NumberKind::Hex,
- },
- kind: TokenKind::Number,
- span: Span::new(start, end),
- })
- }
- fn lex_binary_number(&mut self) -> Result<Token, Diagnostic> {
- self.advance();
- self.advance();
- let start = self.pos;
- let mut end = self.pos;
- let mut number = String::new();
- number.push(self.get_current());
- self.advance();
- while !self.is_eof() {
- let c = self.get_current();
- if "01".contains(c) {
- number.push(c);
- end += 1;
- self.advance();
- } else {
- break;
- }
- }
- let number = INTERNER.write().intern_string(number);
- Ok(Token {
- value: TokenValue::Number {
- value: number,
- kind: NumberKind::Bin,
- },
- kind: TokenKind::Number,
- span: Span::new(start, end),
- })
- }
- fn lex_octal_number(&mut self) -> Result<Token, Diagnostic> {
- self.advance();
- self.advance();
- let start = self.pos;
- let mut end = self.pos;
- let mut number = String::new();
- number.push(self.get_current());
- self.advance();
- while !self.is_eof() {
- let c = self.get_current();
- if "01234567".contains(c) {
- number.push(c);
- end += 1;
- self.advance();
- } else {
- break;
- }
- }
- let number = INTERNER.write().intern_string(number);
- Ok(Token {
- value: TokenValue::Number {
- value: number,
- kind: NumberKind::Oct,
- },
- kind: TokenKind::Number,
- span: Span::new(start, end),
- })
- }
- fn lex_number(&mut self) -> Result<Token, Diagnostic> {
- match self.try_peek_next() {
- Some('x') => self.lex_hex_number(),
- Some('b') => self.lex_binary_number(),
- Some('o') => self.lex_octal_number(),
- _ => self.lex_decimal_number(),
- }
- }
- fn single_char_token(&mut self, kind: TokenKind) -> Token {
- let start = self.pos;
- let end = self.pos;
- self.advance();
- Token {
- value: TokenValue::None,
- kind,
- span: Span::new(start, end),
- }
- }
- fn maybe_double_char_token(
- &mut self,
- kind: TokenKind,
- next: &[char],
- double_kind: &[TokenKind],
- ) -> Token {
- let start = self.pos;
- let end = self.pos;
- self.advance();
- if !self.is_eof() {
- let ch = self.get_current();
- if next.contains(&ch) {
- self.advance();
- return Token {
- value: TokenValue::None,
- kind: double_kind[next.iter().position(|&c| c == ch).unwrap()],
- span: Span::new(start, end + 1),
- };
- }
- }
- Token {
- value: TokenValue::None,
- kind,
- span: Span::new(start, end),
- }
- }
- fn lex_string(&mut self) -> Result<Token, Diagnostic> {
- let start = self.pos;
- let mut end = self.pos;
- let mut string = String::new();
- self.advance();
- loop {
- if self.is_eof() {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UnterminatedString,
- message: "Unterminated string".to_string(),
- span: Span::new(start, end),
- });
- }
- end += 1;
- let c = self.get_current();
- if c == '"' {
- self.advance();
- break;
- } else if c == '\\' {
- let mut esc = "\\".to_string();
- self.advance();
- if self.is_eof() {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UnexpectedToken,
- message: "Unexpected eof".to_string(),
- span: Span::new(start, end + 1),
- });
- }
- esc += &self.get_current().to_string();
- end += 1;
- let escape_char = match esc.as_str() {
- "\\n" => '\n',
- "\\t" => '\t',
- "\\r" => '\r',
- "\\\\" => '\\',
- "\\\"" => '\"',
- _ => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidEscapeCharacter,
- message: "Invalid escape character".to_string(),
- span: Span {
- lo: end - 2,
- hi: end,
- },
- })
- }
- };
- string.push(escape_char);
- self.advance();
- continue;
- }
- string.push(c);
- self.advance();
- }
- Ok(Token {
- value: TokenValue::String(INTERNER.write().intern_string(string)),
- kind: TokenKind::String,
- span: Span::new(start, end - 1),
- })
- }
- pub fn lex_once(&mut self) -> Result<Token, Diagnostic> {
- if self.is_eof() {
- return Ok(Token {
- value: TokenValue::None,
- kind: TokenKind::Eof,
- span: Span::new(self.pos, self.pos),
- });
- }
- match self.get_current() {
- '{' => Ok(self.single_char_token(TokenKind::LeftBrace)),
- '}' => Ok(self.single_char_token(TokenKind::RightBrace)),
- '(' => Ok(self.single_char_token(TokenKind::LeftParen)),
- ')' => Ok(self.single_char_token(TokenKind::RightParen)),
- '[' => Ok(self.single_char_token(TokenKind::LeftBracket)),
- ']' => Ok(self.single_char_token(TokenKind::RightBracket)),
- ',' => Ok(self.single_char_token(TokenKind::Comma)),
- '.' => Ok(self.single_char_token(TokenKind::Dot)),
- ';' => Ok(self.single_char_token(TokenKind::Semicolon)),
- '~' => Ok(self.single_char_token(TokenKind::Tilde)),
- '@' => Ok(self.single_char_token(TokenKind::At)),
- ':' => Ok(self.single_char_token(TokenKind::Colon)),
- '+' => {
- Ok(self.maybe_double_char_token(TokenKind::Plus, &['='], &[TokenKind::PlusEq]))
- }
- '-' => Ok(self.maybe_double_char_token(
- TokenKind::Minus,
- &['='],
- &[TokenKind::MinusEq],
- )),
- '*' => Ok(self.maybe_double_char_token(
- TokenKind::Asterisk,
- &['='],
- &[TokenKind::AsteriskEq],
- )),
- '/' => {
- if self.try_peek_next() == Some('/') {
- self.advance();
- while !self.is_eof() {
- if self.get_current() == '\n' {
- self.advance();
- if !self.is_eof() {
- return self.lex_once();
- }
- }
- self.advance();
- }
- return self.lex_once();
- }
- Ok(self.maybe_double_char_token(
- TokenKind::Slash,
- &['='],
- &[TokenKind::SlashEq],
- ))
- }
- '%' => Ok(self.maybe_double_char_token(
- TokenKind::Percent,
- &['='],
- &[TokenKind::PercentEq],
- )),
- '^' => Ok(self.maybe_double_char_token(
- TokenKind::Caret,
- &['='],
- &[TokenKind::CaretEq],
- )),
- '&' => Ok(self.maybe_double_char_token(
- TokenKind::Ampersand,
- &['&', '='],
- &[TokenKind::DoubleAmpersand, TokenKind::AmpersandEq],
- )),
- '|' => Ok(self.maybe_double_char_token(
- TokenKind::Pipe,
- &['|', '='],
- &[TokenKind::DoublePipe, TokenKind::PipeEq],
- )),
- '!' => Ok(self.maybe_double_char_token(
- TokenKind::Exclamation,
- &['='],
- &[TokenKind::ExclamationEq],
- )),
- '=' => Ok(self.maybe_double_char_token(
- TokenKind::Equal,
- &['='],
- &[TokenKind::DoubleEqual],
- )),
- '<' => Ok({
- if let Some('<') = self.try_peek_next() {
- self.advance();
- if let Some('=') = self.try_peek_next() {
- self.advance();
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::DoubleLeftAngleEq,
- span: Span::new(self.pos - 3, self.pos - 1),
- }
- } else {
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::DoubleLeftAngle,
- span: Span::new(self.pos - 2, self.pos - 1),
- }
- }
- } else if let Some('=') = self.try_peek_next() {
- self.advance();
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::LeftAngleEq,
- span: Span::new(self.pos - 2, self.pos - 1),
- }
- } else {
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::LeftAngle,
- span: Span::new(self.pos - 1, self.pos - 1),
- }
- }
- }),
- '>' => Ok({
- if let Some('>') = self.try_peek_next() {
- self.advance();
- if let Some('=') = self.try_peek_next() {
- self.advance();
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::DoubleRightAngleEq,
- span: Span::new(self.pos - 3, self.pos - 1),
- }
- } else {
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::DoubleRightAngle,
- span: Span::new(self.pos - 2, self.pos - 1),
- }
- }
- } else if let Some('=') = self.try_peek_next() {
- self.advance();
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::RightAngleEq,
- span: Span::new(self.pos - 2, self.pos - 1),
- }
- } else {
- self.advance();
- Token {
- value: TokenValue::None,
- kind: TokenKind::RightAngle,
- span: Span::new(self.pos - 1, self.pos - 1),
- }
- }
- }),
- '"' => self.lex_string(),
- '0'..='9' => self.lex_number(),
- 'a'..='z' | 'A'..='Z' => self.lex_identifier(),
- c if c.is_whitespace() => {
- self.advance();
- self.lex_once()
- }
- _ => {
- let e = Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::UnknownToken,
- message: "Unknown character".to_string(),
- span: self.current_char_span(),
- });
- self.advance();
- e
- }
- }
- }
- fn try_peek_next(&self) -> Option<char> {
- self.source_chars.clone().nth(self.pos + 1)
- }
- fn current_char_span(&self) -> Span {
- Span {
- lo: self.pos,
- hi: self.pos,
- }
- }
- fn get_current(&mut self) -> char {
- self.source_chars.clone().nth(self.pos).unwrap()
- }
- fn is_eof(&self) -> bool {
- self.pos >= self.source_len
- }
- fn advance(&mut self) {
- self.pos += 1;
- }
- }
- pub struct Token {
- pub value: TokenValue,
- pub kind: TokenKind,
- pub span: Span,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Token {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "Token",
- "value",
- &&self.value,
- "kind",
- &&self.kind,
- "span",
- &&self.span,
- )
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for Token {}
- #[automatically_derived]
- impl ::core::clone::Clone for Token {
- #[inline]
- fn clone(&self) -> Token {
- let _: ::core::clone::AssertParamIsClone<TokenValue>;
- let _: ::core::clone::AssertParamIsClone<TokenKind>;
- let _: ::core::clone::AssertParamIsClone<Span>;
- *self
- }
- }
- pub enum TokenValue {
- String(InternedString),
- Number {
- kind: NumberKind,
- value: InternedString,
- },
- None,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for TokenValue {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- TokenValue::String(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "String", &__self_0)
- }
- TokenValue::Number {
- kind: __self_0,
- value: __self_1,
- } => ::core::fmt::Formatter::debug_struct_field2_finish(
- f, "Number", "kind", &__self_0, "value", &__self_1,
- ),
- TokenValue::None => ::core::fmt::Formatter::write_str(f, "None"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for TokenValue {
- #[inline]
- fn clone(&self) -> TokenValue {
- let _: ::core::clone::AssertParamIsClone<InternedString>;
- let _: ::core::clone::AssertParamIsClone<NumberKind>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for TokenValue {}
- impl TokenValue {
- pub fn get_string(&self) -> InternedString {
- match self {
- Self::String(s) => *s,
- _ => ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["TokenValue::get_string() called on non TokenValue::String"],
- &[],
- )),
- }
- }
- pub fn get_number(&self) -> (InternedString, NumberKind) {
- match self {
- Self::Number { value, kind } => (*value, *kind),
- _ => ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["TokenValue::get_string() called on non TokenValue::String"],
- &[],
- )),
- }
- }
- }
- pub enum NumberKind {
- Bin,
- Hex,
- Oct,
- DecInt,
- DecFloat,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for NumberKind {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- NumberKind::Bin => ::core::fmt::Formatter::write_str(f, "Bin"),
- NumberKind::Hex => ::core::fmt::Formatter::write_str(f, "Hex"),
- NumberKind::Oct => ::core::fmt::Formatter::write_str(f, "Oct"),
- NumberKind::DecInt => ::core::fmt::Formatter::write_str(f, "DecInt"),
- NumberKind::DecFloat => ::core::fmt::Formatter::write_str(f, "DecFloat"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for NumberKind {}
- #[automatically_derived]
- impl ::core::clone::Clone for NumberKind {
- #[inline]
- fn clone(&self) -> NumberKind {
- *self
- }
- }
- impl ::core::marker::StructuralPartialEq for NumberKind {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for NumberKind {
- #[inline]
- fn eq(&self, other: &NumberKind) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for NumberKind {
- #[inline]
- fn partial_cmp(&self, other: &NumberKind) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralEq for NumberKind {}
- #[automatically_derived]
- impl ::core::cmp::Eq for NumberKind {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for NumberKind {
- #[inline]
- fn cmp(&self, other: &NumberKind) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl NumberKind {
- pub fn radix(&self) -> u32 {
- match self {
- Self::Bin => 2,
- Self::Hex => 16,
- Self::Oct => 8,
- Self::DecInt | Self::DecFloat => 10,
- }
- }
- }
- pub enum TokenKind {
- String,
- Number,
- Identifier,
- As,
- Const,
- Mut,
- Fun,
- Data,
- Methods,
- Continue,
- Break,
- Loop,
- Iter,
- Ret,
- If,
- Else,
- True,
- False,
- None,
- Plus,
- PlusEq,
- Minus,
- MinusEq,
- Asterisk,
- AsteriskEq,
- Slash,
- SlashEq,
- Percent,
- PercentEq,
- Caret,
- CaretEq,
- Ampersand,
- AmpersandEq,
- DoubleAmpersand,
- Pipe,
- PipeEq,
- DoublePipe,
- Tilde,
- Exclamation,
- ExclamationEq,
- LeftAngle,
- LeftAngleEq,
- DoubleLeftAngle,
- DoubleLeftAngleEq,
- RightAngle,
- RightAngleEq,
- DoubleRightAngle,
- DoubleRightAngleEq,
- Equal,
- DoubleEqual,
- LeftParen,
- RightParen,
- LeftBrace,
- RightBrace,
- LeftBracket,
- RightBracket,
- Comma,
- Dot,
- Colon,
- Semicolon,
- At,
- Eof,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for TokenKind {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- TokenKind::String => ::core::fmt::Formatter::write_str(f, "String"),
- TokenKind::Number => ::core::fmt::Formatter::write_str(f, "Number"),
- TokenKind::Identifier => ::core::fmt::Formatter::write_str(f, "Identifier"),
- TokenKind::As => ::core::fmt::Formatter::write_str(f, "As"),
- TokenKind::Const => ::core::fmt::Formatter::write_str(f, "Const"),
- TokenKind::Mut => ::core::fmt::Formatter::write_str(f, "Mut"),
- TokenKind::Fun => ::core::fmt::Formatter::write_str(f, "Fun"),
- TokenKind::Data => ::core::fmt::Formatter::write_str(f, "Data"),
- TokenKind::Methods => ::core::fmt::Formatter::write_str(f, "Methods"),
- TokenKind::Continue => ::core::fmt::Formatter::write_str(f, "Continue"),
- TokenKind::Break => ::core::fmt::Formatter::write_str(f, "Break"),
- TokenKind::Loop => ::core::fmt::Formatter::write_str(f, "Loop"),
- TokenKind::Iter => ::core::fmt::Formatter::write_str(f, "Iter"),
- TokenKind::Ret => ::core::fmt::Formatter::write_str(f, "Ret"),
- TokenKind::If => ::core::fmt::Formatter::write_str(f, "If"),
- TokenKind::Else => ::core::fmt::Formatter::write_str(f, "Else"),
- TokenKind::True => ::core::fmt::Formatter::write_str(f, "True"),
- TokenKind::False => ::core::fmt::Formatter::write_str(f, "False"),
- TokenKind::None => ::core::fmt::Formatter::write_str(f, "None"),
- TokenKind::Plus => ::core::fmt::Formatter::write_str(f, "Plus"),
- TokenKind::PlusEq => ::core::fmt::Formatter::write_str(f, "PlusEq"),
- TokenKind::Minus => ::core::fmt::Formatter::write_str(f, "Minus"),
- TokenKind::MinusEq => ::core::fmt::Formatter::write_str(f, "MinusEq"),
- TokenKind::Asterisk => ::core::fmt::Formatter::write_str(f, "Asterisk"),
- TokenKind::AsteriskEq => ::core::fmt::Formatter::write_str(f, "AsteriskEq"),
- TokenKind::Slash => ::core::fmt::Formatter::write_str(f, "Slash"),
- TokenKind::SlashEq => ::core::fmt::Formatter::write_str(f, "SlashEq"),
- TokenKind::Percent => ::core::fmt::Formatter::write_str(f, "Percent"),
- TokenKind::PercentEq => ::core::fmt::Formatter::write_str(f, "PercentEq"),
- TokenKind::Caret => ::core::fmt::Formatter::write_str(f, "Caret"),
- TokenKind::CaretEq => ::core::fmt::Formatter::write_str(f, "CaretEq"),
- TokenKind::Ampersand => ::core::fmt::Formatter::write_str(f, "Ampersand"),
- TokenKind::AmpersandEq => ::core::fmt::Formatter::write_str(f, "AmpersandEq"),
- TokenKind::DoubleAmpersand => {
- ::core::fmt::Formatter::write_str(f, "DoubleAmpersand")
- }
- TokenKind::Pipe => ::core::fmt::Formatter::write_str(f, "Pipe"),
- TokenKind::PipeEq => ::core::fmt::Formatter::write_str(f, "PipeEq"),
- TokenKind::DoublePipe => ::core::fmt::Formatter::write_str(f, "DoublePipe"),
- TokenKind::Tilde => ::core::fmt::Formatter::write_str(f, "Tilde"),
- TokenKind::Exclamation => ::core::fmt::Formatter::write_str(f, "Exclamation"),
- TokenKind::ExclamationEq => ::core::fmt::Formatter::write_str(f, "ExclamationEq"),
- TokenKind::LeftAngle => ::core::fmt::Formatter::write_str(f, "LeftAngle"),
- TokenKind::LeftAngleEq => ::core::fmt::Formatter::write_str(f, "LeftAngleEq"),
- TokenKind::DoubleLeftAngle => {
- ::core::fmt::Formatter::write_str(f, "DoubleLeftAngle")
- }
- TokenKind::DoubleLeftAngleEq => {
- ::core::fmt::Formatter::write_str(f, "DoubleLeftAngleEq")
- }
- TokenKind::RightAngle => ::core::fmt::Formatter::write_str(f, "RightAngle"),
- TokenKind::RightAngleEq => ::core::fmt::Formatter::write_str(f, "RightAngleEq"),
- TokenKind::DoubleRightAngle => {
- ::core::fmt::Formatter::write_str(f, "DoubleRightAngle")
- }
- TokenKind::DoubleRightAngleEq => {
- ::core::fmt::Formatter::write_str(f, "DoubleRightAngleEq")
- }
- TokenKind::Equal => ::core::fmt::Formatter::write_str(f, "Equal"),
- TokenKind::DoubleEqual => ::core::fmt::Formatter::write_str(f, "DoubleEqual"),
- TokenKind::LeftParen => ::core::fmt::Formatter::write_str(f, "LeftParen"),
- TokenKind::RightParen => ::core::fmt::Formatter::write_str(f, "RightParen"),
- TokenKind::LeftBrace => ::core::fmt::Formatter::write_str(f, "LeftBrace"),
- TokenKind::RightBrace => ::core::fmt::Formatter::write_str(f, "RightBrace"),
- TokenKind::LeftBracket => ::core::fmt::Formatter::write_str(f, "LeftBracket"),
- TokenKind::RightBracket => ::core::fmt::Formatter::write_str(f, "RightBracket"),
- TokenKind::Comma => ::core::fmt::Formatter::write_str(f, "Comma"),
- TokenKind::Dot => ::core::fmt::Formatter::write_str(f, "Dot"),
- TokenKind::Colon => ::core::fmt::Formatter::write_str(f, "Colon"),
- TokenKind::Semicolon => ::core::fmt::Formatter::write_str(f, "Semicolon"),
- TokenKind::At => ::core::fmt::Formatter::write_str(f, "At"),
- TokenKind::Eof => ::core::fmt::Formatter::write_str(f, "Eof"),
- }
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for TokenKind {}
- #[automatically_derived]
- impl ::core::clone::Clone for TokenKind {
- #[inline]
- fn clone(&self) -> TokenKind {
- *self
- }
- }
- impl ::core::marker::StructuralPartialEq for TokenKind {}
- #[automatically_derived]
- impl ::core::cmp::PartialEq for TokenKind {
- #[inline]
- fn eq(&self, other: &TokenKind) -> bool {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- __self_tag == __arg1_tag
- }
- }
- #[automatically_derived]
- impl ::core::cmp::PartialOrd for TokenKind {
- #[inline]
- fn partial_cmp(&self, other: &TokenKind) -> ::core::option::Option<::core::cmp::Ordering> {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag)
- }
- }
- impl ::core::marker::StructuralEq for TokenKind {}
- #[automatically_derived]
- impl ::core::cmp::Eq for TokenKind {
- #[inline]
- #[doc(hidden)]
- #[no_coverage]
- fn assert_receiver_is_total_eq(&self) -> () {}
- }
- #[automatically_derived]
- impl ::core::cmp::Ord for TokenKind {
- #[inline]
- fn cmp(&self, other: &TokenKind) -> ::core::cmp::Ordering {
- let __self_tag = ::core::intrinsics::discriminant_value(self);
- let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag)
- }
- }
- }
- mod memory {
- use crate::interner::InternedString;
- use std::collections::HashMap;
- use std::fmt::Debug;
- use crate::ast::{DataStmt, FunStmt};
- use crate::diagnostics::Diagnostic;
- use crate::Interpreter;
- use parking_lot::RwLock;
- use std::sync::Arc;
- pub struct Allocator {
- allocations: Vec<Arc<RwLock<Value>>>,
- }
- impl Allocator {
- pub const fn new() -> Self {
- Self {
- allocations: alloc::vec::Vec::new(),
- }
- }
- pub fn get_none(&self) -> ValueAddr {
- ValueAddr(0)
- }
- pub fn allocate(&mut self, value: Value) -> ValueAddr {
- if self.allocations.is_empty() {
- self.allocations.push(Arc::new(RwLock::new(Value::None)));
- }
- if match value {
- Value::None => true,
- _ => false,
- } {
- return ValueAddr(0);
- }
- self.allocations.push(Arc::new(RwLock::new(value)));
- ValueAddr(self.allocations.len() - 1)
- }
- pub fn clone(&mut self, addr: ValueAddr) -> ValueAddr {
- let value_arc = self.allocations[addr.0].clone();
- let value_read = value_arc.read();
- let cloned_value = match &*value_read {
- Value::Int(i) => Value::Int(*i),
- Value::Float(f) => Value::Float(*f),
- Value::Boolean(b) => Value::Boolean(*b),
- Value::String(s) => Value::String(*s),
- Value::None => Value::None,
- Value::Function(_f) => return addr,
- Value::Data(d, m) => Value::Data(d.clone(), m.clone()),
- Value::DataObject(d_object) => Value::DataObject(d_object.clone()),
- Value::Array(a) => Value::Array(a.clone()),
- };
- self.allocations.push(Arc::new(RwLock::new(cloned_value)));
- ValueAddr(self.allocations.len() - 1)
- }
- pub fn deallocate(&mut self, addr: ValueAddr) {
- if let Some(obj) = self.allocations.get(addr.0) {
- if Arc::strong_count(obj) == 0 {
- self.allocations.remove(addr.0);
- }
- }
- }
- pub fn get(&self, addr: ValueAddr) -> Arc<RwLock<Value>> {
- self.allocations[addr.0].clone()
- }
- }
- pub struct ValueAddr(usize);
- #[automatically_derived]
- impl ::core::fmt::Debug for ValueAddr {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "ValueAddr", &&self.0)
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for ValueAddr {
- #[inline]
- fn clone(&self) -> ValueAddr {
- let _: ::core::clone::AssertParamIsClone<usize>;
- *self
- }
- }
- #[automatically_derived]
- impl ::core::marker::Copy for ValueAddr {}
- pub enum Value {
- Int(i64),
- Float(f64),
- Boolean(bool),
- String(InternedString),
- None,
- Function(Box<dyn Callable>),
- Data(Box<DataStmt>, HashMap<InternedString, Box<FunStmt>>),
- DataObject(DataObject),
- Array(Vec<ValueAddr>),
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Value {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match self {
- Value::Int(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int", &__self_0)
- }
- Value::Float(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Float", &__self_0)
- }
- Value::Boolean(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Boolean", &__self_0)
- }
- Value::String(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "String", &__self_0)
- }
- Value::None => ::core::fmt::Formatter::write_str(f, "None"),
- Value::Function(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Function", &__self_0)
- }
- Value::Data(__self_0, __self_1) => {
- ::core::fmt::Formatter::debug_tuple_field2_finish(
- f, "Data", &__self_0, &__self_1,
- )
- }
- Value::DataObject(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "DataObject", &__self_0)
- }
- Value::Array(__self_0) => {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Array", &__self_0)
- }
- }
- }
- }
- impl Value {
- pub fn type_(&self) -> String {
- String::from(match self {
- Value::Int(_) => "int",
- Value::Float(_) => "float",
- Value::Boolean(_) => "boolean",
- Value::String(_) => "string",
- Value::None => "none",
- Value::Function(_) => "function",
- Value::DataObject(_) => "data object",
- Value::Data(_, _) => "data",
- Value::Array(_) => "array",
- })
- }
- }
- pub trait Callable: Debug + Send + Sync {
- fn arity(&self) -> usize;
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic>;
- fn to_string(&self) -> String;
- fn clone(&self) -> Self
- where
- Self: Sized;
- }
- pub struct DataObject {
- pub name: InternedString,
- pub values: HashMap<InternedString, ValueAddr>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for DataObject {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field2_finish(
- f,
- "DataObject",
- "name",
- &&self.name,
- "values",
- &&self.values,
- )
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for DataObject {
- #[inline]
- fn clone(&self) -> DataObject {
- DataObject {
- name: ::core::clone::Clone::clone(&self.name),
- values: ::core::clone::Clone::clone(&self.values),
- }
- }
- }
- }
- mod native {
- use crate::diagnostics::{Diagnostic, ErrorCode, Severity, Span};
- use crate::interner::INTERNER;
- use crate::memory::{Allocator, Value};
- use crate::memory::{Callable, ValueAddr};
- use crate::Interpreter;
- use std::io::Write;
- use std::thread::sleep;
- use std::time::Duration;
- pub struct PrintFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for PrintFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "PrintFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for PrintFunction {
- #[inline]
- fn clone(&self) -> PrintFunction {
- PrintFunction {}
- }
- }
- impl PrintFunction {
- pub fn stringify_value(allocator: &Allocator, value: &Value) -> String {
- match &*value {
- Value::Int(i) => i.to_string(),
- Value::Float(f) => f.to_string(),
- Value::Boolean(b) => b.to_string(),
- Value::String(s) => INTERNER.read().get_interned_string(*s).to_string(),
- Value::None => "None".to_string(),
- Value::Function(f) => f.to_string(),
- Value::Data(_, _) => "<data>".to_string(),
- Value::DataObject(_) => {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<data object at 0x", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(value as *const _))],
- ));
- res
- }
- Value::Array(a) => {
- let mut res = String::from("[");
- let mut str_vals = alloc::vec::Vec::new();
- for v in a {
- let val = allocator.get(*v);
- let val_reader = val.read();
- if let Value::String(s) = &*val_reader {
- str_vals.push({
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &[""],
- &[::core::fmt::ArgumentV1::new_debug(
- &INTERNER.read().get_interned_string(*s),
- )],
- ));
- res
- });
- } else {
- str_vals.push(Self::stringify_value(allocator, &*val_reader));
- }
- }
- res.push_str(&str_vals.join(", "));
- res.push(']');
- res
- }
- }
- }
- }
- impl Callable for PrintFunction {
- fn arity(&self) -> usize {
- usize::MAX
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- for arg in args {
- let value = interpreter.get_allocator().get(arg);
- let value_read = value.read();
- {
- ::std::io::_print(::core::fmt::Arguments::new_v1(
- &[""],
- &[::core::fmt::ArgumentV1::new_display(
- &Self::stringify_value(interpreter.get_allocator_mut(), &*value_read),
- )],
- ));
- };
- std::io::stdout().flush().unwrap();
- }
- Ok(None)
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"print\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct PrintlnFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for PrintlnFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "PrintlnFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for PrintlnFunction {
- #[inline]
- fn clone(&self) -> PrintlnFunction {
- PrintlnFunction {}
- }
- }
- impl Callable for PrintlnFunction {
- fn arity(&self) -> usize {
- usize::MAX
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- PrintFunction {}.call(interpreter, args)?;
- {
- ::std::io::_print(::core::fmt::Arguments::new_v1(&["\n"], &[]));
- };
- std::io::stdout().flush().unwrap();
- Ok(None)
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"println\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct SleepFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for SleepFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "SleepFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for SleepFunction {
- #[inline]
- fn clone(&self) -> SleepFunction {
- SleepFunction {}
- }
- }
- impl Callable for SleepFunction {
- fn arity(&self) -> usize {
- 1
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let time_addr = args[0];
- let time_container = interpreter.get_allocator().get(time_addr);
- let time_read = time_container.read();
- let time = match &*time_read {
- Value::Int(i) => *i as f64,
- Value::Float(f) => *f,
- val => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Expected type `int` or `float`, found type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&val.type_())],
- ));
- res
- },
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- })
- }
- };
- sleep(Duration::from_secs_f64(time));
- Ok(None)
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"sleep\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct ArrayPopFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for ArrayPopFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "ArrayPopFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for ArrayPopFunction {
- #[inline]
- fn clone(&self) -> ArrayPopFunction {
- ArrayPopFunction {}
- }
- }
- impl Callable for ArrayPopFunction {
- fn arity(&self) -> usize {
- 1
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let array_addr = args[0];
- let array_container = interpreter.get_allocator().get(array_addr);
- let mut array_read = array_container.write();
- let array = match &mut *array_read {
- Value::Array(arr) => arr,
- val => {
- return Err(Diagnostic {
- severity: Severity::Error,
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Expected type `array`, found type `", "`"],
- &[::core::fmt::ArgumentV1::new_display(&val.type_())],
- ));
- res
- },
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- })
- }
- };
- Ok(array.pop())
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"sleep\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct InputFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for InputFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "InputFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for InputFunction {
- #[inline]
- fn clone(&self) -> InputFunction {
- InputFunction {}
- }
- }
- impl Callable for InputFunction {
- fn arity(&self) -> usize {
- usize::MAX
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- if !args.is_empty() {
- PrintFunction {}.call(interpreter, args)?;
- }
- let mut line = String::new();
- loop {
- let size = std::io::stdin().read_line(&mut line).unwrap();
- if size > 1 {
- break;
- }
- }
- line.pop();
- Ok(Some(interpreter.get_allocator_mut().allocate(
- Value::String(INTERNER.write().intern_string(line)),
- )))
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"input\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct IntFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for IntFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "IntFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for IntFunction {
- #[inline]
- fn clone(&self) -> IntFunction {
- IntFunction {}
- }
- }
- impl Callable for IntFunction {
- fn arity(&self) -> usize {
- 1
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let n_s = args[0];
- let n_container = interpreter.get_allocator().get(n_s);
- let n_read = n_container.read();
- let res: i64 = match &*n_read {
- Value::String(s) => match INTERNER.read().get_interned_string(*s).parse() {
- Ok(res) => res,
- Err(e) => {
- return Err(Diagnostic {
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- code: ErrorCode::InvalidNumber,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Failed to parse number: "],
- &[::core::fmt::ArgumentV1::new_display(&e)],
- ));
- res
- },
- severity: Severity::Error,
- })
- }
- },
- Value::Float(f) => *f as _,
- Value::Int(i) => *i,
- _ => {
- return Err(Diagnostic {
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Expected type `string`, `float` or `int`, found "],
- &[::core::fmt::ArgumentV1::new_display(&n_read.type_())],
- ));
- res
- },
- severity: Severity::Error,
- })
- }
- };
- Ok(Some(
- interpreter.get_allocator_mut().allocate(Value::Int(res)),
- ))
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"input\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- pub struct FloatFunction {}
- #[automatically_derived]
- impl ::core::fmt::Debug for FloatFunction {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::write_str(f, "FloatFunction")
- }
- }
- #[automatically_derived]
- impl ::core::clone::Clone for FloatFunction {
- #[inline]
- fn clone(&self) -> FloatFunction {
- FloatFunction {}
- }
- }
- impl Callable for FloatFunction {
- fn arity(&self) -> usize {
- 1
- }
- fn call(
- &self,
- interpreter: &mut Interpreter,
- args: Vec<ValueAddr>,
- ) -> Result<Option<ValueAddr>, Diagnostic> {
- let n_s = args[0];
- let n_container = interpreter.get_allocator().get(n_s);
- let n_read = n_container.read();
- let res: f64 = match &*n_read {
- Value::String(s) => match INTERNER.read().get_interned_string(*s).parse() {
- Ok(res) => res,
- Err(e) => {
- return Err(Diagnostic {
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- code: ErrorCode::InvalidNumber,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Failed to parse number: "],
- &[::core::fmt::ArgumentV1::new_display(&e)],
- ));
- res
- },
- severity: Severity::Error,
- })
- }
- },
- Value::Float(f) => *f,
- Value::Int(i) => *i as _,
- _ => {
- return Err(Diagnostic {
- span: Span {
- lo: usize::MAX,
- hi: usize::MAX,
- },
- code: ErrorCode::InvalidType,
- message: {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["Expected type `string`, `float` or `int`, found "],
- &[::core::fmt::ArgumentV1::new_display(&n_read.type_())],
- ));
- res
- },
- severity: Severity::Error,
- })
- }
- };
- Ok(Some(
- interpreter.get_allocator_mut().allocate(Value::Float(res)),
- ))
- }
- fn to_string(&self) -> String {
- {
- let res = alloc::fmt::format(::core::fmt::Arguments::new_v1(
- &["<native function \"input\" at ", ">"],
- &[::core::fmt::ArgumentV1::new_pointer(&(self as *const _))],
- ));
- res
- }
- }
- fn clone(&self) -> Self
- where
- Self: Sized,
- {
- Clone::clone(self)
- }
- }
- }
- mod parser {
- use crate::ast::{
- AssignmentExpr, BinaryExpr, BinaryOperation, CallExpr, DataExpr, DataStmt, Expr,
- ExprContainer, FunStmt, GetExpr, IfStmt, IndexExpr, IndexSetExpr, IterStmt, LogicalExpr,
- LogicalOperation, MethodsStmt, Mutable, NumberExpr, SetExpr, Stmt, StmtContainer,
- UnaryExpr, UnaryOperation, VarStmt,
- };
- use crate::diagnostics::{Diagnostic, ErrorCode, Severity};
- use crate::lexer::{Lexer, Token, TokenKind};
- use std::collections::HashMap;
- pub struct Parser {
- tokens: Vec<Token>,
- diagnostics: Vec<Diagnostic>,
- pos: usize,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Parser {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field3_finish(
- f,
- "Parser",
- "tokens",
- &&self.tokens,
- "diagnostics",
- &&self.diagnostics,
- "pos",
- &&self.pos,
- )
- }
- }
- impl Parser {
- pub fn new(source: &str) -> Self {
- let mut lexer = Lexer::new(source);
- let mut tokens = alloc::vec::Vec::new();
- let mut lexer_diags = alloc::vec::Vec::new();
- loop {
- let res = lexer.lex_once();
- if let Ok(token) = res {
- tokens.push(token);
- if token.kind == TokenKind::Eof {
- break;
- }
- } else if let Err(e) = res {
- lexer_diags.push(e);
- }
- }
- Self {
- tokens,
- diagnostics: lexer_diags,
- pos: 0,
- }
- }
- fn expect(&mut self, kind: TokenKind) -> Result<Token, Diagnostic> {
- let token = self.peek();
- if token.kind == kind {
- self.advance();
- Ok(token)
- } else if token.kind == TokenKind::Eof {
- Err(Self::error_for_token(
- ErrorCode::UnexpectedToken,
- "unexpected end of file",
- token,
- ))
- } else {
- Err(Self::error_for_token(
- ErrorCode::UnexpectedToken,
- "Unexpected token",
- token,
- ))
- }
- }
- fn previous(&self) -> Token {
- self.tokens[self.pos - 1]
- }
- fn unless(&mut self, kind: TokenKind) -> Result<bool, Diagnostic> {
- if self.is_eof() {
- Err(Self::error_for_token(
- ErrorCode::UnexpectedToken,
- "unexpected end of file",
- self.peek(),
- ))
- } else if self.peek().kind == kind {
- self.advance();
- Ok(true)
- } else {
- Ok(false)
- }
- }
- fn advance(&mut self) {
- self.pos += 1;
- }
- fn peek(&self) -> Token {
- self.tokens[self.pos]
- }
- fn is_eof(&self) -> bool {
- self.peek().kind == TokenKind::Eof
- }
- pub fn parse(&mut self) -> Vec<StmtContainer> {
- let mut stmts = alloc::vec::Vec::new();
- while !self.is_eof() {
- let res = self.declaration();
- if let Ok(stmt) = res {
- stmts.push(stmt);
- } else if let Err(e) = res {
- self.diagnostics.push(e);
- self.synchronize();
- }
- }
- stmts
- }
- fn synchronize(&mut self) {
- if self.is_eof() {
- return;
- }
- self.advance();
- loop {
- match self.previous().kind {
- TokenKind::Semicolon
- | TokenKind::LeftBrace
- | TokenKind::RightBrace
- | TokenKind::If
- | TokenKind::Const
- | TokenKind::Mut
- | TokenKind::Loop
- | TokenKind::Iter
- | TokenKind::Fun
- | TokenKind::Data
- | TokenKind::Continue
- | TokenKind::Break
- | TokenKind::Ret
- | TokenKind::Methods
- | TokenKind::Eof => break,
- _ => (),
- }
- self.advance();
- }
- }
- fn declaration(&mut self) -> Result<StmtContainer, Diagnostic> {
- match self.peek().kind {
- TokenKind::Const => self.var_declaration(Mutable::No),
- TokenKind::Mut => self.var_declaration(Mutable::Yes),
- TokenKind::Fun => self.fun_stmt(false),
- TokenKind::Data => self.data_stmt(),
- TokenKind::Methods => self.methods_stmt(),
- _ => {
- let token = self.peek();
- self.advance();
- Err(Self::error_for_token(
- ErrorCode::UnexpectedToken,
- "unexpected token",
- token,
- ))
- }
- }
- }
- fn data_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- let name = self.expect(TokenKind::Identifier)?.value.get_string();
- let mut fields = alloc::vec::Vec::new();
- self.expect(TokenKind::LeftBrace)?;
- let mut is_first_property = true;
- while !self.unless(TokenKind::RightBrace)? {
- if !is_first_property {
- self.expect(TokenKind::Comma)?;
- } else {
- is_first_property = false;
- }
- fields.push(self.expect(TokenKind::Identifier)?.value.get_string());
- }
- Ok(Stmt::Data(Box::new(DataStmt { name, fields }))
- .into_container(start_span.merge(self.previous().span)))
- }
- fn methods_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- let data = self.expect(TokenKind::Identifier)?.value.get_string();
- let mut methods = alloc::vec::Vec::new();
- self.expect(TokenKind::LeftBrace)?;
- while !self.unless(TokenKind::RightBrace)? {
- methods.push(self.fun_stmt(true)?);
- }
- Ok(Stmt::Methods(Box::new(MethodsStmt { methods, data }))
- .into_container(start_span.merge(self.previous().span)))
- }
- fn var_declaration(&mut self, mutable: Mutable) -> Result<StmtContainer, Diagnostic> {
- let span_start = self.peek().span;
- self.advance();
- let name = self.expect(TokenKind::Identifier)?.value.get_string();
- self.expect(TokenKind::Equal)?;
- let value = self.expr()?;
- self.expect(TokenKind::Semicolon)?;
- Ok(Stmt::Var(Box::new(VarStmt {
- name,
- value,
- mutable,
- }))
- .into_container(span_start.merge(self.previous().span)))
- }
- fn fun_stmt(&mut self, is_method: bool) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- let name = self.expect(TokenKind::Identifier)?.value.get_string();
- self.expect(TokenKind::LeftParen)?;
- let mut arguments = alloc::vec::Vec::new();
- let mut is_first_arg = true;
- loop {
- if match self.peek().kind {
- TokenKind::RightParen => true,
- _ => false,
- } {
- break;
- }
- if !is_first_arg {
- self.expect(TokenKind::Comma)?;
- } else {
- is_first_arg = false;
- }
- let current_token = self.peek();
- if current_token.kind == TokenKind::Identifier {
- self.advance();
- arguments.push(current_token.value.get_string());
- } else {
- self.advance();
- break;
- }
- }
- self.expect(TokenKind::RightParen)?;
- let body = self.block_stmt()?;
- Ok(Stmt::Fun(Box::new(FunStmt {
- name,
- arguments,
- body,
- is_method,
- }))
- .into_container(start_span.merge(self.peek().span)))
- }
- fn ret_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- let expr = self.expr()?;
- self.expect(TokenKind::Semicolon)?;
- Ok(Stmt::Ret(expr).into_container(start_span.merge(self.previous().span)))
- }
- fn iter_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- let iterable = self.expr()?;
- self.expect(TokenKind::Colon)?;
- let binding = self.expect(TokenKind::Identifier)?.value.get_string();
- let block = self.block_stmt()?;
- Ok(Stmt::Iter(Box::new(IterStmt {
- iterable,
- binding,
- block,
- }))
- .into_container(start_span.merge(self.previous().span)))
- }
- fn if_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- self.advance();
- self.expect(TokenKind::LeftParen)?;
- let condition = self.expr()?;
- self.expect(TokenKind::RightParen)?;
- let block = self.block_stmt()?;
- let else_;
- let mut then = None;
- if self.peek().kind == TokenKind::Else {
- self.advance();
- if self.peek().kind == TokenKind::If {
- else_ = Some(self.if_stmt()?);
- } else {
- else_ = None;
- then = Some(self.block_stmt()?);
- }
- } else {
- else_ = None;
- }
- Ok(Stmt::If(Box::new(IfStmt {
- condition,
- block,
- else_,
- then,
- }))
- .into_container(start_span.merge(self.previous().span)))
- }
- fn block_stmt(&mut self) -> Result<StmtContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut stmts = alloc::vec::Vec::new();
- self.expect(TokenKind::LeftBrace)?;
- while !self.unless(TokenKind::RightBrace)? {
- let res = match self.peek().kind {
- TokenKind::Const => self.var_declaration(Mutable::No),
- TokenKind::Mut => self.var_declaration(Mutable::Yes),
- TokenKind::LeftBrace => self.block_stmt(),
- TokenKind::Ret => self.ret_stmt(),
- TokenKind::Continue => {
- let span = self.peek().span;
- self.advance();
- self.expect(TokenKind::Semicolon)?;
- Ok(Stmt::Continue.into_container(span.merge(self.previous().span)))
- }
- TokenKind::Break => {
- let span = self.peek().span;
- self.advance();
- self.expect(TokenKind::Semicolon)?;
- Ok(Stmt::Break.into_container(span.merge(self.previous().span)))
- }
- TokenKind::Loop => {
- let span = self.peek().span;
- self.advance();
- let block = self.block_stmt()?;
- Ok(Stmt::Loop(Box::new(block))
- .into_container(span.merge(self.previous().span)))
- }
- TokenKind::Iter => self.iter_stmt(),
- TokenKind::If => self.if_stmt(),
- _ => {
- let expr = self.expr()?;
- let span = expr.span;
- self.expect(TokenKind::Semicolon)?;
- Ok(Stmt::Expr(expr).into_container(span))
- }
- };
- if let Ok(res) = res {
- stmts.push(res);
- } else if let Err(e) = res {
- self.diagnostics.push(e);
- self.synchronize();
- }
- }
- Ok(Stmt::Block(stmts).into_container(start_span.merge(self.previous().span)))
- }
- fn expr(&mut self) -> Result<ExprContainer, Diagnostic> {
- self.assignment()
- }
- fn assignment(&mut self) -> Result<ExprContainer, Diagnostic> {
- let mut data_member = false;
- let start_span = self.peek().span;
- if self.peek().kind == TokenKind::At {
- data_member = true;
- self.advance();
- }
- let expr = self.logical_or()?;
- match self.peek().kind {
- TokenKind::DoubleLeftAngleEq
- | TokenKind::DoubleRightAngleEq
- | TokenKind::PlusEq
- | TokenKind::MinusEq
- | TokenKind::AsteriskEq
- | TokenKind::SlashEq
- | TokenKind::PercentEq
- | TokenKind::AmpersandEq
- | TokenKind::PipeEq
- | TokenKind::CaretEq => {
- let op = match self.peek().kind {
- TokenKind::DoubleLeftAngleEq => BinaryOperation::LeftShift,
- TokenKind::DoubleRightAngleEq => BinaryOperation::RightShift,
- TokenKind::PlusEq => BinaryOperation::Plus,
- TokenKind::MinusEq => BinaryOperation::Minus,
- TokenKind::AsteriskEq => BinaryOperation::Multiply,
- TokenKind::SlashEq => BinaryOperation::Divide,
- TokenKind::PercentEq => BinaryOperation::Modulus,
- TokenKind::AmpersandEq => BinaryOperation::And,
- TokenKind::PipeEq => BinaryOperation::Or,
- TokenKind::CaretEq => BinaryOperation::Xor,
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- };
- let eq_token = self.peek();
- self.advance();
- let rhs = self.expr()?;
- return match &expr.expr {
- Expr::Get(get_expr) => Ok(Expr::Set(Box::new(SetExpr {
- property: get_expr.property,
- object: expr.clone(),
- value: Expr::Binary(Box::new(BinaryExpr {
- lhs: expr.clone(),
- op,
- rhs,
- }))
- .into_container(start_span.merge(self.peek().span)),
- }))
- .into_container(start_span.merge(self.peek().span))),
- Expr::Index(_) => Ok(Expr::IndexSet(Box::new(IndexSetExpr {
- object: expr.clone(),
- value: Expr::Binary(Box::new(BinaryExpr {
- lhs: expr.clone(),
- op,
- rhs,
- }))
- .into_container(start_span.merge(self.peek().span)),
- }))
- .into_container(start_span.merge(self.peek().span))),
- Expr::Variable(_) => Ok(Expr::Assignment(Box::new(AssignmentExpr {
- lvalue: expr.clone(),
- data_member,
- rvalue: Expr::Binary(Box::new(BinaryExpr {
- lhs: expr.clone(),
- op,
- rhs,
- }))
- .into_container(start_span.merge(self.peek().span)),
- }))
- .into_container(start_span.merge(self.peek().span))),
- _ => Err(Self::error_for_token(
- ErrorCode::InvalidAssignment,
- "invalid assignment target",
- eq_token,
- )),
- };
- }
- _ => (),
- }
- if self.peek().kind == TokenKind::Equal {
- let eq_token = self.peek();
- self.advance();
- let rhs = self.expr()?;
- return match &expr.expr {
- Expr::Get(get_expr) => {
- let expr = get_expr.clone();
- Ok(Expr::Set(Box::new(SetExpr {
- property: expr.property,
- object: expr.object,
- value: rhs,
- }))
- .into_container(start_span.merge(self.peek().span)))
- }
- Expr::Index(_) => Ok(Expr::IndexSet(Box::new(IndexSetExpr {
- object: expr,
- value: rhs,
- }))
- .into_container(start_span.merge(self.peek().span))),
- Expr::Variable(_name) => Ok(Expr::Assignment(Box::new(AssignmentExpr {
- data_member,
- lvalue: expr,
- rvalue: rhs,
- }))
- .into_container(start_span.merge(self.peek().span))),
- _ => Err(Self::error_for_token(
- ErrorCode::InvalidAssignment,
- "invalid assignment target",
- eq_token,
- )),
- };
- }
- Ok(expr)
- }
- fn logical_or(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.logical_and()?;
- let mut op;
- loop {
- op = LogicalOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == LogicalOperation::Or {
- self.advance();
- let rhs = self.logical_and()?;
- expr = Expr::Logical(Box::new(LogicalExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn logical_and(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.equality()?;
- let mut op;
- loop {
- op = LogicalOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == LogicalOperation::And {
- self.advance();
- let rhs = self.equality()?;
- expr = Expr::Logical(Box::new(LogicalExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn equality(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.comparison()?;
- let mut op;
- loop {
- op = LogicalOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == LogicalOperation::Equals || op == LogicalOperation::NotEquals {
- self.advance();
- let rhs = self.comparison()?;
- expr = Expr::Logical(Box::new(LogicalExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn comparison(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.bitwise_or()?;
- let mut op;
- loop {
- op = LogicalOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == LogicalOperation::LessThan
- || op == LogicalOperation::LessThanOrEquals
- || op == LogicalOperation::GreaterThan
- || op == LogicalOperation::GreaterThanOrEquals
- {
- self.advance();
- let rhs = self.bitwise_or()?;
- expr = Expr::Logical(Box::new(LogicalExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn bitwise_or(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.bitwise_xor()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::Or {
- self.advance();
- let rhs = self.bitwise_xor()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn bitwise_xor(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.bitwise_and()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::Xor {
- self.advance();
- let rhs = self.bitwise_and()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn bitwise_and(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.bitwise_shift()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::And {
- self.advance();
- let rhs = self.bitwise_shift()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn bitwise_shift(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.term()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::LeftShift || op == BinaryOperation::RightShift {
- self.advance();
- let rhs = self.term()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn term(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.factor()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::Plus || op == BinaryOperation::Minus {
- self.advance();
- let rhs = self.factor()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn factor(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.unary()?;
- let mut op;
- loop {
- op = BinaryOperation::try_from(self.peek().kind);
- if let Ok(op) = op {
- if op == BinaryOperation::Multiply || op == BinaryOperation::Divide {
- self.advance();
- let rhs = self.unary()?;
- expr = Expr::Binary(Box::new(BinaryExpr { lhs: expr, op, rhs }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn unary(&mut self) -> Result<ExprContainer, Diagnostic> {
- let op = match UnaryOperation::try_from(self.peek().kind) {
- Ok(op) => op,
- Err(_) => return self.callexpr(),
- };
- let start_span = self.peek().span;
- self.advance();
- Ok(Expr::Unary(Box::new(UnaryExpr {
- expr: self.unary()?,
- op,
- }))
- .into_container(start_span.merge(self.peek().span)))
- }
- fn callexpr(&mut self) -> Result<ExprContainer, Diagnostic> {
- let start_span = self.peek().span;
- let mut expr = self.primary()?;
- loop {
- if self.peek().kind == TokenKind::LeftParen {
- self.advance();
- let args = self.arguments()?;
- self.expect(TokenKind::RightParen)?;
- expr = Expr::Call(Box::new(CallExpr { callee: expr, args }))
- .into_container(start_span.merge(self.peek().span));
- } else if self.peek().kind == TokenKind::Dot {
- self.advance();
- let name = self.expect(TokenKind::Identifier)?;
- expr = Expr::Get(Box::new(GetExpr {
- property: name.value.get_string(),
- object: expr,
- }))
- .into_container(start_span.merge(self.peek().span));
- } else {
- break;
- }
- }
- Ok(expr)
- }
- fn arguments(&mut self) -> Result<Vec<ExprContainer>, Diagnostic> {
- let mut args = alloc::vec::Vec::new();
- if self.peek().kind == TokenKind::RightParen {
- return Ok(args);
- }
- args.push(self.expr()?);
- loop {
- if self.peek().kind != TokenKind::Comma {
- break;
- }
- self.advance();
- args.push(self.expr()?);
- }
- Ok(args)
- }
- fn primary(&mut self) -> Result<ExprContainer, Diagnostic> {
- let current_token = self.peek();
- self.advance();
- match current_token.kind {
- TokenKind::True => Ok(Expr::Boolean(true).into_container(current_token.span)),
- TokenKind::False => Ok(Expr::Boolean(false).into_container(current_token.span)),
- TokenKind::None => Ok(Expr::None.into_container(current_token.span)),
- TokenKind::Identifier => {
- let start_span = self.peek().span;
- let mut expr = Expr::Variable(current_token.value.get_string())
- .into_container(current_token.span);
- if self.peek().kind == TokenKind::LeftBracket {
- self.advance();
- let index = self.expr()?;
- self.expect(TokenKind::RightBracket)?;
- expr = Expr::Index(Box::new(IndexExpr {
- object: expr,
- index,
- }))
- .into_container(start_span.merge(self.previous().span));
- } else if self.peek().kind == TokenKind::LeftBrace {
- self.advance();
- let name = match expr.expr {
- Expr::Variable(n) => n,
- _ => {
- ::core::panicking::panic("internal error: entered unreachable code")
- }
- };
- let mut props = HashMap::new();
- let mut is_first_prop = true;
- let mut err = None;
- while !self.unless(TokenKind::RightBrace)? {
- if !is_first_prop {
- self.expect(TokenKind::Comma)?;
- } else {
- is_first_prop = false;
- }
- let prop_span = self.peek().span;
- let prop = self.expect(TokenKind::Identifier)?.value.get_string();
- self.expect(TokenKind::Colon)?;
- let value = self.expr()?;
- let sp = prop_span.merge(value.span);
- if let Some(_) = props.insert(prop, value) {
- err = Some(Diagnostic {
- code: ErrorCode::InvalidDataPropertySet,
- severity: Severity::Error,
- message: String::from(
- "Attempt to set same property more than once",
- ),
- span: sp,
- })
- }
- }
- if let Some(e) = err {
- return Err(e);
- }
- expr = Expr::Data(Box::new(DataExpr { name, props }))
- .into_container(start_span.merge(self.previous().span));
- }
- Ok(expr)
- }
- TokenKind::String => Ok(Expr::String(current_token.value.get_string())
- .into_container(current_token.span)),
- TokenKind::Number => {
- let (value, kind) = current_token.value.get_number();
- Ok(Expr::Number(NumberExpr { kind, value }).into_container(current_token.span))
- }
- TokenKind::LeftParen => {
- let expr = self.expr()?;
- self.expect(TokenKind::RightParen)?;
- Ok(Expr::Grouping(Box::new(expr)).into_container(current_token.span))
- }
- TokenKind::LeftBracket => {
- let mut exprs = alloc::vec::Vec::new();
- let mut is_first_item = true;
- while !self.unless(TokenKind::RightBracket)? {
- if !is_first_item {
- self.expect(TokenKind::Comma)?;
- } else {
- is_first_item = false;
- }
- exprs.push(self.expr()?);
- }
- Ok(Expr::Array(exprs).into_container(current_token.span))
- }
- _ => Err(Self::error_for_token(
- ErrorCode::UnexpectedToken,
- "expected primary expression",
- current_token,
- )),
- }
- }
- fn error_for_token(code: ErrorCode, message: &str, token: Token) -> Diagnostic {
- Diagnostic {
- severity: Severity::Error,
- code,
- message: message.to_string(),
- span: token.span,
- }
- }
- pub fn get_diagnostics(self) -> Vec<Diagnostic> {
- self.diagnostics
- }
- }
- }
- mod session {
- use crate::diagnostics::{Diagnostic, Severity};
- use crate::interner::{InternedString, INTERNER};
- use crate::analyzer::Analyzer;
- use crate::ast::StmtContainer;
- use crate::parser::Parser;
- use std::collections::HashMap;
- pub struct Session {
- pub entry_point: InternedString,
- pub debug: bool,
- pub files: HashMap<InternedString, String>,
- asts: HashMap<InternedString, Vec<StmtContainer>>,
- diagnostics: HashMap<InternedString, Vec<Diagnostic>>,
- }
- #[automatically_derived]
- impl ::core::fmt::Debug for Session {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_struct_field5_finish(
- f,
- "Session",
- "entry_point",
- &&self.entry_point,
- "debug",
- &&self.debug,
- "files",
- &&self.files,
- "asts",
- &&self.asts,
- "diagnostics",
- &&self.diagnostics,
- )
- }
- }
- impl Session {
- pub fn from_file(filename: String, file: String, debug: bool) -> Self {
- let filename = INTERNER.write().intern_string(filename);
- let mut files = HashMap::new();
- files.insert(filename, file);
- Self {
- entry_point: filename,
- files,
- diagnostics: HashMap::new(),
- asts: HashMap::new(),
- debug,
- }
- }
- pub fn parse(&mut self, file: InternedString) {
- let file_content = &self.files[&file];
- let mut parser = Parser::new(file_content);
- let stmts = parser.parse();
- self.diagnostics.insert(file, parser.get_diagnostics());
- let analyzer = Analyzer::new(&stmts);
- analyzer.analyze();
- self.diagnostics
- .get_mut(&file)
- .unwrap()
- .extend(analyzer.get_diagnostics());
- if self.debug {
- match &stmts {
- tmp => {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1_formatted(
- &["[", ":", "] ", " = ", "\n"],
- &match (&"src/session.rs", &48u32, &"&stmts", &&tmp) {
- args => [
- ::core::fmt::ArgumentV1::new_display(args.0),
- ::core::fmt::ArgumentV1::new_display(args.1),
- ::core::fmt::ArgumentV1::new_display(args.2),
- ::core::fmt::ArgumentV1::new_debug(args.3),
- ],
- },
- &[
- ::core::fmt::rt::v1::Argument {
- position: 0usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 1usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 2usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 0u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ::core::fmt::rt::v1::Argument {
- position: 3usize,
- format: ::core::fmt::rt::v1::FormatSpec {
- fill: ' ',
- align: ::core::fmt::rt::v1::Alignment::Unknown,
- flags: 4u32,
- precision: ::core::fmt::rt::v1::Count::Implied,
- width: ::core::fmt::rt::v1::Count::Implied,
- },
- },
- ],
- unsafe { ::core::fmt::UnsafeArg::new() },
- ));
- };
- tmp
- }
- };
- }
- self.asts.insert(file, stmts);
- }
- pub fn parse_entrypoint(&mut self) {
- self.parse(self.entry_point);
- }
- pub fn has_diagnostics(&self) -> bool {
- for (_, diags) in &self.diagnostics {
- for diag in diags {
- if diag.severity == Severity::Error {
- return true;
- }
- }
- }
- false
- }
- pub fn print_diagnostics(&self) {
- for (filename, diagnostics) in &self.diagnostics {
- for diagnostic in diagnostics {
- {
- ::std::io::_eprint(::core::fmt::Arguments::new_v1(
- &["", "\n"],
- &[::core::fmt::ArgumentV1::new_display(&diagnostic.display(
- INTERNER.read().get_interned_string(*filename),
- self.files.get(filename).unwrap(),
- ))],
- ));
- };
- }
- }
- }
- pub fn get_ast(&self, file_name: InternedString) -> &[StmtContainer] {
- &self.asts[&file_name]
- }
- }
- }
- fn main() {
- let args = std::env::args().collect::<Vec<String>>();
- let file_name = &args[1];
- let file_content = std::fs::read_to_string(file_name).unwrap();
- let mut session = Session::from_file(
- file_name.clone(),
- file_content,
- args.contains(&String::from("--debug")),
- );
- let mut interpreter = Interpreter::new(&mut session);
- if interpreter.init() {
- interpreter.interpret();
- }
- }
Add Comment
Please, Sign In to add comment