refactor: namespaces(?)
And move list functions over there
This commit is contained in:
parent
285b93aa89
commit
ab20f6e85e
5 changed files with 231 additions and 213 deletions
193
mute-interpreter/src/env/core.rs
vendored
193
mute-interpreter/src/env/core.rs
vendored
|
@ -1,5 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::{borrow::Borrow, collections::VecDeque};
|
borrow::Borrow,
|
||||||
|
collections::{HashMap, VecDeque},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{macros::arg_count, NativeFunc, Value};
|
use super::{macros::arg_count, NativeFunc, Value};
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
|
@ -170,18 +172,6 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
Node::List(list)
|
Node::List(list)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"list?",
|
|
||||||
NativeFunc(|args| {
|
|
||||||
arg_count!(1, args.len());
|
|
||||||
|
|
||||||
if let Node::List(_list) = args[0].borrow() {
|
|
||||||
return Node::Boolean(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::Boolean(false)
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
("vector", NativeFunc(|args| Node::Vector(args.into()))),
|
("vector", NativeFunc(|args| Node::Vector(args.into()))),
|
||||||
(
|
(
|
||||||
"vector?",
|
"vector?",
|
||||||
|
@ -229,38 +219,6 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
Node::Boolean(false)
|
Node::Boolean(false)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"empty?",
|
|
||||||
NativeFunc(|mut args| {
|
|
||||||
arg_count!(1, args.len());
|
|
||||||
|
|
||||||
match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(list) => Node::Boolean(list.is_empty()),
|
|
||||||
Node::Vector(vec) => Node::Boolean(vec.is_empty()),
|
|
||||||
Node::Hashmap(map) => Node::Boolean(map.is_empty()),
|
|
||||||
arg => Node::Error(format!(
|
|
||||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"count",
|
|
||||||
NativeFunc(|mut args| {
|
|
||||||
arg_count!(1, args.len());
|
|
||||||
|
|
||||||
match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(list) => Node::Int(list.len() as i64),
|
|
||||||
Node::Vector(vec) => Node::Int(vec.len() as i64),
|
|
||||||
Node::Hashmap(map) => Node::Int(map.len() as i64),
|
|
||||||
arg => Node::Error(format!(
|
|
||||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
// Strings
|
// Strings
|
||||||
(
|
(
|
||||||
"str",
|
"str",
|
||||||
|
@ -272,149 +230,6 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
// List stuff
|
// List stuff
|
||||||
(
|
|
||||||
"first",
|
|
||||||
NativeFunc(|args| {
|
|
||||||
arg_count!(1, args.len());
|
|
||||||
|
|
||||||
match args[0].borrow() {
|
|
||||||
Node::List(list) if list.is_empty() => Node::Nil,
|
|
||||||
Node::Vector(vec) if vec.is_empty() => Node::Nil,
|
|
||||||
Node::List(list) => list.front().unwrap().clone(),
|
|
||||||
Node::Vector(vec) => vec.first().unwrap().clone(),
|
|
||||||
arg => Node::Error(format!(
|
|
||||||
"TypeError: expected list or vector, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"last",
|
|
||||||
NativeFunc(|mut args| {
|
|
||||||
arg_count!(1, args.len());
|
|
||||||
|
|
||||||
match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(list) if list.is_empty() => Node::Nil,
|
|
||||||
Node::Vector(list) if list.is_empty() => Node::Nil,
|
|
||||||
|
|
||||||
Node::List(list) => list.back().unwrap().clone(),
|
|
||||||
Node::Vector(vec) => vec.last().unwrap().clone(),
|
|
||||||
arg => Node::Error(format!(
|
|
||||||
"TypeError: expected list or vector, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"nth",
|
|
||||||
NativeFunc(|mut args| {
|
|
||||||
arg_count!(2, args.len());
|
|
||||||
|
|
||||||
let list = match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(list) => list,
|
|
||||||
Node::Vector(vec) => vec.into(),
|
|
||||||
arg => {
|
|
||||||
return Node::Error(format!(
|
|
||||||
"TypeError: expected list or vector, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let nth = match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::Int(val) => val as usize,
|
|
||||||
Node::Float(val) => val as usize,
|
|
||||||
arg => {
|
|
||||||
return Node::Error(format!(
|
|
||||||
"TypeError: expected int or float, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if nth < 1 {
|
|
||||||
return Node::Error(format!("TypeError: expected positive int, got {}", nth));
|
|
||||||
}
|
|
||||||
|
|
||||||
list.get(nth - 1).unwrap().clone()
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"push-back",
|
|
||||||
NativeFunc(
|
|
||||||
|mut args| match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(mut list) => {
|
|
||||||
while let Some(val) = args.pop_front() {
|
|
||||||
list.push_back(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::List(list)
|
|
||||||
}
|
|
||||||
Node::Vector(mut vec) => {
|
|
||||||
while let Some(val) = args.pop_front() {
|
|
||||||
vec.push(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::Vector(vec)
|
|
||||||
}
|
|
||||||
arg => Node::Error(format!(
|
|
||||||
"TypeError: expected list or vector, got {}.",
|
|
||||||
arg.get_type()
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"push-front",
|
|
||||||
NativeFunc(
|
|
||||||
|mut args| match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(mut list) => {
|
|
||||||
while let Some(val) = args.pop_back() {
|
|
||||||
list.push_front(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::List(list)
|
|
||||||
}
|
|
||||||
arg => {
|
|
||||||
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"pop-front",
|
|
||||||
NativeFunc(
|
|
||||||
|mut args| match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(mut list) => {
|
|
||||||
list.pop_front();
|
|
||||||
Node::List(list)
|
|
||||||
}
|
|
||||||
arg => {
|
|
||||||
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"pop-back",
|
|
||||||
NativeFunc(
|
|
||||||
|mut args| match args.pop_front().expect("argument length checked above") {
|
|
||||||
Node::List(mut list) => {
|
|
||||||
list.pop_back();
|
|
||||||
Node::List(list)
|
|
||||||
}
|
|
||||||
Node::Vector(mut vec) => {
|
|
||||||
vec.pop();
|
|
||||||
Node::Vector(vec)
|
|
||||||
}
|
|
||||||
arg => {
|
|
||||||
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (k.to_string(), Value::NativeFunc(v)))
|
.map(|(k, v)| (k.to_string(), Value::NativeFunc(v)))
|
||||||
|
|
200
mute-interpreter/src/env/list.rs
vendored
Normal file
200
mute-interpreter/src/env/list.rs
vendored
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use super::{macros::arg_count, NativeFunc, Value};
|
||||||
|
use crate::Node;
|
||||||
|
|
||||||
|
pub(super) fn lib() -> HashMap<String, Value> {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"list?",
|
||||||
|
NativeFunc(|args| {
|
||||||
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
|
if let Node::List(_list) = args[0].borrow() {
|
||||||
|
return Node::Boolean(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::Boolean(false)
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"empty?",
|
||||||
|
NativeFunc(|mut args| {
|
||||||
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
|
match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(list) => Node::Boolean(list.is_empty()),
|
||||||
|
Node::Vector(vec) => Node::Boolean(vec.is_empty()),
|
||||||
|
Node::Hashmap(map) => Node::Boolean(map.is_empty()),
|
||||||
|
arg => Node::Error(format!(
|
||||||
|
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"count",
|
||||||
|
NativeFunc(|mut args| {
|
||||||
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
|
match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(list) => Node::Int(list.len() as i64),
|
||||||
|
Node::Vector(vec) => Node::Int(vec.len() as i64),
|
||||||
|
Node::Hashmap(map) => Node::Int(map.len() as i64),
|
||||||
|
arg => Node::Error(format!(
|
||||||
|
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"first",
|
||||||
|
NativeFunc(|args| {
|
||||||
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
|
match args[0].borrow() {
|
||||||
|
Node::List(list) if list.is_empty() => Node::Nil,
|
||||||
|
Node::Vector(vec) if vec.is_empty() => Node::Nil,
|
||||||
|
Node::List(list) => list.front().unwrap().clone(),
|
||||||
|
Node::Vector(vec) => vec.first().unwrap().clone(),
|
||||||
|
arg => Node::Error(format!(
|
||||||
|
"TypeError: expected list or vector, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"last",
|
||||||
|
NativeFunc(|mut args| {
|
||||||
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
|
match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(list) if list.is_empty() => Node::Nil,
|
||||||
|
Node::Vector(list) if list.is_empty() => Node::Nil,
|
||||||
|
|
||||||
|
Node::List(list) => list.back().unwrap().clone(),
|
||||||
|
Node::Vector(vec) => vec.last().unwrap().clone(),
|
||||||
|
arg => Node::Error(format!(
|
||||||
|
"TypeError: expected list or vector, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"nth",
|
||||||
|
NativeFunc(|mut args| {
|
||||||
|
arg_count!(2, args.len());
|
||||||
|
|
||||||
|
let list = match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(list) => list,
|
||||||
|
Node::Vector(vec) => vec.into(),
|
||||||
|
arg => {
|
||||||
|
return Node::Error(format!(
|
||||||
|
"TypeError: expected list or vector, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let nth = match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::Int(val) => val as usize,
|
||||||
|
Node::Float(val) => val as usize,
|
||||||
|
arg => {
|
||||||
|
return Node::Error(format!(
|
||||||
|
"TypeError: expected int or float, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if nth < 1 {
|
||||||
|
return Node::Error(format!("TypeError: expected positive int, got {}", nth));
|
||||||
|
}
|
||||||
|
|
||||||
|
list.get(nth - 1).unwrap().clone()
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"push-back",
|
||||||
|
NativeFunc(
|
||||||
|
|mut args| match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(mut list) => {
|
||||||
|
while let Some(val) = args.pop_front() {
|
||||||
|
list.push_back(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::List(list)
|
||||||
|
}
|
||||||
|
Node::Vector(mut vec) => {
|
||||||
|
while let Some(val) = args.pop_front() {
|
||||||
|
vec.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::Vector(vec)
|
||||||
|
}
|
||||||
|
arg => Node::Error(format!(
|
||||||
|
"TypeError: expected list or vector, got {}.",
|
||||||
|
arg.get_type()
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"push-front",
|
||||||
|
NativeFunc(
|
||||||
|
|mut args| match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(mut list) => {
|
||||||
|
while let Some(val) = args.pop_back() {
|
||||||
|
list.push_front(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::List(list)
|
||||||
|
}
|
||||||
|
arg => {
|
||||||
|
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pop-front",
|
||||||
|
NativeFunc(
|
||||||
|
|mut args| match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(mut list) => {
|
||||||
|
list.pop_front();
|
||||||
|
Node::List(list)
|
||||||
|
}
|
||||||
|
arg => {
|
||||||
|
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pop-back",
|
||||||
|
NativeFunc(
|
||||||
|
|mut args| match args.pop_front().expect("argument length checked above") {
|
||||||
|
Node::List(mut list) => {
|
||||||
|
list.pop_back();
|
||||||
|
Node::List(list)
|
||||||
|
}
|
||||||
|
Node::Vector(mut vec) => {
|
||||||
|
vec.pop();
|
||||||
|
Node::Vector(vec)
|
||||||
|
}
|
||||||
|
arg => {
|
||||||
|
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (format!("List.{k}"), Value::NativeFunc(v)))
|
||||||
|
.collect()
|
||||||
|
}
|
3
mute-interpreter/src/env/mod.rs
vendored
3
mute-interpreter/src/env/mod.rs
vendored
|
@ -6,6 +6,7 @@ use crate::Node;
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
mod io;
|
mod io;
|
||||||
|
mod list;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod standard;
|
mod standard;
|
||||||
|
|
||||||
|
@ -74,10 +75,12 @@ impl std::default::Default for Environment {
|
||||||
let mut env = HashMap::new();
|
let mut env = HashMap::new();
|
||||||
let core = core::core();
|
let core = core::core();
|
||||||
let io = io::io();
|
let io = io::io();
|
||||||
|
let list = list::lib();
|
||||||
let stdlib = standard::standard();
|
let stdlib = standard::standard();
|
||||||
|
|
||||||
env.extend(core);
|
env.extend(core);
|
||||||
env.extend(io);
|
env.extend(io);
|
||||||
|
env.extend(list);
|
||||||
env.extend(stdlib);
|
env.extend(stdlib);
|
||||||
|
|
||||||
let env = RawEnvironment {
|
let env = RawEnvironment {
|
||||||
|
|
|
@ -456,30 +456,30 @@ mod test {
|
||||||
#[case("{:a \"uwu\"}", "{:a: uwu}")]
|
#[case("{:a \"uwu\"}", "{:a: uwu}")]
|
||||||
// Lists
|
// Lists
|
||||||
#[case("(list 1 2 3)", "(1 2 3)")]
|
#[case("(list 1 2 3)", "(1 2 3)")]
|
||||||
#[case("(list? (list))", "true")]
|
#[case("(List.list? (list))", "true")]
|
||||||
#[case("(list? 23)", "false")]
|
#[case("(List.list? 23)", "false")]
|
||||||
#[case("(empty? (list 1 2 3))", "false")]
|
|
||||||
#[case("(empty? (list))", "true")]
|
|
||||||
#[case("(count (list))", "0")]
|
|
||||||
#[case("(count (list 1 2 3))", "3")]
|
|
||||||
#[case("(range 5)", "(1 2 3 4 5)")]
|
#[case("(range 5)", "(1 2 3 4 5)")]
|
||||||
#[case("(range 6 10)", "(6 7 8 9 10)")]
|
#[case("(range 6 10)", "(6 7 8 9 10)")]
|
||||||
|
#[case("(List.empty? (list 1 2 3))", "false")]
|
||||||
|
#[case("(List.empty? (list))", "true")]
|
||||||
|
#[case("(List.count (list))", "0")]
|
||||||
|
#[case("(List.count (list 1 2 3))", "3")]
|
||||||
// Vectors
|
// Vectors
|
||||||
#[case("(vector 1 2 3)", "[1 2 3]")]
|
#[case("(vector 1 2 3)", "[1 2 3]")]
|
||||||
#[case("(vector? [])", "true")]
|
#[case("(vector? [])", "true")]
|
||||||
#[case("(vector? 23)", "false")]
|
#[case("(vector? 23)", "false")]
|
||||||
#[case("(empty? [1 2 3])", "false")]
|
#[case("(List.empty? [1 2 3])", "false")]
|
||||||
#[case("(empty? [])", "true")]
|
#[case("(List.empty? [])", "true")]
|
||||||
#[case("(count [])", "0")]
|
#[case("(List.count [])", "0")]
|
||||||
#[case("(count [1 2 3])", "3")]
|
#[case("(List.count [1 2 3])", "3")]
|
||||||
// Hashmaps
|
// Hashmaps
|
||||||
#[case("(hashmap :a 1)", "{:a: 1}")]
|
#[case("(hashmap :a 1)", "{:a: 1}")]
|
||||||
#[case("(hashmap? {})", "true")]
|
#[case("(hashmap? {})", "true")]
|
||||||
#[case("(hashmap? 23)", "false")]
|
#[case("(hashmap? 23)", "false")]
|
||||||
#[case("(empty? {:a 1})", "false")]
|
#[case("(List.empty? {:a 1})", "false")]
|
||||||
#[case("(empty? {})", "true")]
|
#[case("(List.empty? {})", "true")]
|
||||||
#[case("(count {})", "0")]
|
#[case("(List.count {})", "0")]
|
||||||
#[case("(count {:a 1})", "1")]
|
#[case("(List.count {:a 1})", "1")]
|
||||||
// Environment manipulation
|
// Environment manipulation
|
||||||
#[case("(define (asdf (+ 2 2))) (+ asdf 2)", "6")]
|
#[case("(define (asdf (+ 2 2))) (+ asdf 2)", "6")]
|
||||||
#[case("(define (add (fn* (a b) (+ a b)))) (add 1 2)", "3")]
|
#[case("(define (add (fn* (a b) (+ a b)))) (add 1 2)", "3")]
|
||||||
|
@ -526,15 +526,15 @@ mod test {
|
||||||
#[case("(str (+ 1 2))", "3")]
|
#[case("(str (+ 1 2))", "3")]
|
||||||
#[case("(str (list 1 2 3))", "(1 2 3)")]
|
#[case("(str (list 1 2 3))", "(1 2 3)")]
|
||||||
// List Manipulation
|
// List Manipulation
|
||||||
#[case("(first (list 1 2 3))", "1")]
|
#[case("(List.first (list 1 2 3))", "1")]
|
||||||
#[case("(last (list 1 2 3))", "3")]
|
#[case("(List.last (list 1 2 3))", "3")]
|
||||||
#[case("(nth (list 1 2 3) 2)", "2")]
|
#[case("(List.nth (list 1 2 3) 2)", "2")]
|
||||||
#[case("(push-front (list 1 2 3) 0)", "(0 1 2 3)")]
|
#[case("(List.push-front (list 1 2 3) 0)", "(0 1 2 3)")]
|
||||||
#[case("(push-back (list 1 2 3) 4)", "(1 2 3 4)")]
|
#[case("(List.push-back (list 1 2 3) 4)", "(1 2 3 4)")]
|
||||||
#[case("(pop-front (list 1 2 3))", "(2 3)")]
|
#[case("(List.pop-front (list 1 2 3))", "(2 3)")]
|
||||||
#[case("(pop-back (list 1 2 3))", "(1 2)")]
|
#[case("(List.pop-back (list 1 2 3))", "(1 2)")]
|
||||||
#[case("(push-back [1 2 3] 4)", "[1 2 3 4]")]
|
#[case("(List.push-back [1 2 3] 4)", "[1 2 3 4]")]
|
||||||
#[case("(pop-back [1 2 3 4])", "[1 2 3]")]
|
#[case("(List.pop-back [1 2 3 4])", "[1 2 3]")]
|
||||||
// Iteration
|
// Iteration
|
||||||
#[case("(map '(1 2 3) (fn* (x) (* x x)))", "(1 4 9)")]
|
#[case("(map '(1 2 3) (fn* (x) (* x x)))", "(1 4 9)")]
|
||||||
#[case("(filter '(1 2 3) (fn* (x) (> x 1)))", "(2 3)")]
|
#[case("(filter '(1 2 3) (fn* (x) (> x 1)))", "(2 3)")]
|
||||||
|
|
|
@ -199,7 +199,7 @@ fn read_int(input: &mut Peekable<Chars>, first: char) -> Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
||||||
let special_characters = ['!', '?', '*', '-', '_'];
|
let special_characters = ['!', '?', '*', '-', '_', '.'];
|
||||||
let mut raw_ident = vec![first];
|
let mut raw_ident = vec![first];
|
||||||
|
|
||||||
while let Some(c) = input.peek() {
|
while let Some(c) = input.peek() {
|
||||||
|
|
Loading…
Reference in a new issue