added first step for db queries
This commit is contained in:
parent
8eeb09855f
commit
05d241b97a
15 changed files with 246 additions and 70 deletions
82
Cargo.lock
generated
82
Cargo.lock
generated
|
|
@ -304,9 +304,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
|
|
@ -492,9 +492,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.9"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
|
|
@ -935,13 +935,13 @@ checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
|||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.10"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1207,7 +1207,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.5.18",
|
||||
"smallvec",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
|
@ -1255,6 +1255,20 @@ version = "0.3.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "postgres"
|
||||
version = "0.19.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c48ece1c6cda0db61b058c1721378da76855140e9214339fa1317decacb176"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fallible-iterator",
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tokio-postgres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postgres-protocol"
|
||||
version = "0.6.9"
|
||||
|
|
@ -1280,6 +1294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"fallible-iterator",
|
||||
"postgres-protocol",
|
||||
]
|
||||
|
|
@ -1326,6 +1341,27 @@ version = "5.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "r2d2"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
|
||||
dependencies = [
|
||||
"log",
|
||||
"parking_lot",
|
||||
"scheduled-thread-pool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r2d2_postgres"
|
||||
version = "0.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd4b47636dbca581cd057e2f27a5d39be741ea4f85fd3c29e415c55f71c7595"
|
||||
dependencies = [
|
||||
"postgres",
|
||||
"r2d2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
|
|
@ -1364,6 +1400,15 @@ dependencies = [
|
|||
"bitflags 2.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.2"
|
||||
|
|
@ -1525,6 +1570,15 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scheduled-thread-pool"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
|
||||
dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
|
|
@ -1876,12 +1930,14 @@ dependencies = [
|
|||
"log",
|
||||
"log4rs",
|
||||
"notify",
|
||||
"postgres",
|
||||
"r2d2",
|
||||
"r2d2_postgres",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-postgres",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-livereload",
|
||||
|
|
@ -2147,18 +2203,18 @@ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
|
||||
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-properties"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
|
||||
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ axum = "0.8.6"
|
|||
log4rs = "1.4.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
tokio = { version = "1.47", features = ["full"] }
|
||||
tokio-postgres = "0.7"
|
||||
chrono = "0.4.42"
|
||||
chrono = "0.4"
|
||||
dotenv = "0.15.0"
|
||||
reqwest = { version = "0.12", features = ["json", "multipart"] }
|
||||
tower-http = { version = "0.6", features = ["fs"] }
|
||||
|
|
@ -26,3 +25,6 @@ clap = { version = "4.5.51", features = ["derive"] }
|
|||
notify = "8.2.0"
|
||||
arc-swap = "1.7.1"
|
||||
regex = "1.12.2"
|
||||
r2d2 = "0.8.10"
|
||||
postgres = { version = "0.19", features = ["with-chrono-0_4"] }
|
||||
r2d2_postgres = "0.18.2"
|
||||
|
|
@ -232,3 +232,9 @@ fn add(a: string, b: string) -> string:
|
|||
ISSUES
|
||||
* Make everything an expression. If is a statement and so it can not be type checked
|
||||
* improve indenting
|
||||
|
||||
WIP guards
|
||||
* | /$uuid -> service.get(uuid)?
|
||||
| /&first_name -> service.get_by_firstname(first_name)?
|
||||
| /&last_name -> service.get_by_lastname(last_name)?
|
||||
| 404
|
||||
|
|
@ -1,5 +1,2 @@
|
|||
fn get(id: u32) -> Customer:
|
||||
select id, first_name, last_name from customers where id = :id
|
||||
|
||||
fn save(c: Customer):
|
||||
insert into customers values(id, first_name, last_name) values(:c.id, :c.first_name, :c.last_name)
|
||||
fn get_all() -> list:
|
||||
sql("select id, first_name, last_name from customers")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,2 @@
|
|||
fn get(id: u32) -> Customer:
|
||||
let customer = dao.get(id)
|
||||
customer.date_fetched = current_date
|
||||
|
||||
fn add(customer: Customer):
|
||||
dao.save(customer)
|
||||
fn get_all() -> list:
|
||||
db::get_all()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
fn get():
|
||||
| path == "/" -> list:
|
||||
service.get_all()
|
||||
| path == "/{uuid}" -> Customer?:
|
||||
service.get(uuid)?
|
||||
| path == "/" && query.firstname -> Customer?:
|
||||
service.get_by_firstname(fname)?
|
||||
| path == "/" && query.last_name -> Customer?
|
||||
service.get_by_lastname(lname)?
|
||||
| 404
|
||||
fn get() -> list:
|
||||
service::get_all()
|
||||
|
||||
fn post(customer: Customer):
|
||||
service.add(customer)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,55 @@
|
|||
use std::cell::{RefMut};
|
||||
use crate::builtins::{FunctionMap, Signature, add};
|
||||
use crate::compiler::tokens::TokenType::{DateTime, StringType, Void};
|
||||
use crate::compiler::ast_pass::Parameter;
|
||||
use crate::compiler::tokens::TokenType;
|
||||
use crate::compiler::tokens::TokenType::{DateTime, ListType, StringType, Void};
|
||||
use crate::errors::RuntimeError;
|
||||
use crate::value::Value;
|
||||
use crate::value::{Value, string};
|
||||
use r2d2_postgres::PostgresConnectionManager;
|
||||
use r2d2_postgres::postgres::NoTls;
|
||||
use r2d2_postgres::postgres::types::Type;
|
||||
use std::cell::RefMut;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
use crate::compiler::ast_pass::Parameter;
|
||||
|
||||
pub(crate) static DB_POOL: LazyLock<r2d2::Pool<PostgresConnectionManager<NoTls>>> =
|
||||
LazyLock::new(|| {
|
||||
let manager = PostgresConnectionManager::new(
|
||||
"host=localhost user=postgres dbname=postgres password=boompje".parse().unwrap(),
|
||||
NoTls,
|
||||
);
|
||||
|
||||
r2d2::Pool::builder()
|
||||
.max_size(15)
|
||||
.build(manager)
|
||||
.expect("Failed to create pool")
|
||||
});
|
||||
|
||||
pub(crate) static GLOBAL_FUNCTIONS: LazyLock<FunctionMap> = LazyLock::new(|| {
|
||||
let mut global_functions: FunctionMap = HashMap::new();
|
||||
let functions = &mut global_functions;
|
||||
add(functions, "now", Signature::new(vec![], DateTime, now));
|
||||
add(functions, "print", Signature::new(vec![Parameter::new("text", StringType)], Void, print));
|
||||
add(functions, "println", Signature::new(vec![Parameter::new("text", StringType)], Void, println));
|
||||
add(
|
||||
functions,
|
||||
"print",
|
||||
Signature::new(vec![Parameter::new("text", StringType)], Void, print),
|
||||
);
|
||||
add(
|
||||
functions,
|
||||
"println",
|
||||
Signature::new(vec![Parameter::new("text", StringType)], Void, println),
|
||||
);
|
||||
add(
|
||||
functions,
|
||||
"sql",
|
||||
Signature::new(
|
||||
vec![
|
||||
Parameter::new("query", StringType),
|
||||
Parameter::varargs(TokenType::Any),
|
||||
],
|
||||
ListType,
|
||||
sql,
|
||||
),
|
||||
);
|
||||
|
||||
global_functions
|
||||
});
|
||||
|
|
@ -31,7 +68,46 @@ fn print(_self_val: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeErr
|
|||
}
|
||||
|
||||
fn now(_self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
Ok(Value::DateTime(Box::new(
|
||||
chrono::Utc::now(),
|
||||
)))
|
||||
Ok(Value::DateTime(Box::new(chrono::Utc::now())))
|
||||
}
|
||||
|
||||
fn sql(_self_val: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
let mut conn = DB_POOL.get().unwrap();
|
||||
let result = conn.query(&args[0].to_string(), &[]).unwrap();
|
||||
let mut columns = vec![];
|
||||
|
||||
if let Some(first_row) = result.first() {
|
||||
let retrieved_columns = first_row.columns();
|
||||
for column in retrieved_columns {
|
||||
columns.push((column.name(), column.type_()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut rows = vec![];
|
||||
for result_row in &result {
|
||||
let mut row: HashMap<Value, Value> = HashMap::new();
|
||||
for (index, column) in result_row.columns().iter().enumerate() {
|
||||
let column_name = columns.get(index).unwrap().0;
|
||||
let column_type = columns.get(index).unwrap().1;
|
||||
let value = match column_type {
|
||||
&Type::BOOL => Value::Bool(result_row.get(index)),
|
||||
&Type::INT2 | &Type::INT4 => Value::I32(result_row.get(index)),
|
||||
&Type::INT8 => Value::I64(result_row.get(index)),
|
||||
&Type::FLOAT4 => Value::F32(result_row.get(index)),
|
||||
&Type::FLOAT8 | &Type::NUMERIC => Value::F64(result_row.get(index)),
|
||||
&Type::CHAR | &Type::VARCHAR | &Type::TEXT | &Type::BPCHAR | &Type::NAME => {
|
||||
Value::String(result_row.get(index))
|
||||
}
|
||||
&Type::TIMESTAMP | &Type::TIMESTAMPTZ => {
|
||||
Value::DateTime(Box::new(result_row.get(index)))
|
||||
}
|
||||
&Type::UUID => Value::Uuid(result_row.get(index)),
|
||||
_ => unimplemented!("database type {:?}", column_type),
|
||||
};
|
||||
|
||||
row.insert(string(column_name), value);
|
||||
}
|
||||
rows.push(Value::Map(row));
|
||||
}
|
||||
Ok(Value::List(rows))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
mod string;
|
||||
mod list;
|
||||
pub(crate) mod globals;
|
||||
mod list;
|
||||
mod map;
|
||||
mod string;
|
||||
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use crate::builtins::list::list_functions;
|
||||
use crate::builtins::map::map_functions;
|
||||
use crate::builtins::string::string_functions;
|
||||
use crate::errors::{CompilerError, RuntimeError};
|
||||
use crate::compiler::ast_pass::Parameter;
|
||||
use crate::compiler::tokens::TokenType;
|
||||
use crate::errors::{CompilerError, RuntimeError};
|
||||
use crate::value::Value;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::LazyLock;
|
||||
use crate::compiler::ast_pass::Parameter;
|
||||
use crate::builtins::list::list_functions;
|
||||
use crate::builtins::map::map_functions;
|
||||
|
||||
pub(crate) struct Signature {
|
||||
pub(crate) parameters: Vec<Parameter>,
|
||||
|
|
@ -37,6 +37,10 @@ impl Signature {
|
|||
pub(crate) fn arity(&self) -> u8 {
|
||||
self.parameters.len() as u8
|
||||
}
|
||||
|
||||
pub(crate) fn has_varargs(&self) -> bool {
|
||||
self.parameters.last().unwrap().name.lexeme == "varargs"
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type FunctionFn = fn(RefMut<Value>, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||
|
|
@ -58,8 +62,11 @@ pub(crate) fn add(m: &mut FunctionMap, name: &str, method: Signature) {
|
|||
m.insert(name.to_string(), method);
|
||||
}
|
||||
|
||||
pub(crate) fn lookup(type_name: &str, method_name: &str) -> Result<&'static Signature, CompilerError> {
|
||||
FUNCTIONS
|
||||
pub(crate) fn lookup(
|
||||
type_name: &str,
|
||||
method_name: &str,
|
||||
) -> Result<&'static Signature, CompilerError> {
|
||||
FUNCTIONS
|
||||
.get(type_name)
|
||||
.and_then(|methods| methods.get(method_name))
|
||||
.ok_or_else(|| CompilerError::FunctionNotFound(format!("{}.{}", type_name, method_name)))
|
||||
|
|
@ -71,7 +78,9 @@ pub(crate) fn call(
|
|||
self_val: Rc<RefCell<Value>>,
|
||||
args: Vec<Value>,
|
||||
) -> Result<Value, RuntimeError> {
|
||||
(lookup(type_name,method_name).map_err(|e|RuntimeError::FunctionNotFound(e.to_string()))?.function)(self_val.borrow_mut(), args)
|
||||
(lookup(type_name, method_name)
|
||||
.map_err(|e| RuntimeError::FunctionNotFound(e.to_string()))?
|
||||
.function)(self_val.borrow_mut(), args)
|
||||
}
|
||||
|
||||
pub(crate) fn expected(expected_type: &str) -> RuntimeError {
|
||||
|
|
|
|||
|
|
@ -295,7 +295,12 @@ impl AsmPass {
|
|||
let name_index = self.chunk.find_constant(name).unwrap_or_else(|| {
|
||||
self.chunk.add_constant(Value::String(name.to_string()))
|
||||
});
|
||||
self.emit(Call(name_index, fun.arity()));
|
||||
let arity = if fun.has_varargs() {
|
||||
arguments.len() as u8
|
||||
} else {
|
||||
fun.arity()
|
||||
};
|
||||
self.emit(Call(name_index, arity));
|
||||
} else {
|
||||
return Err(self
|
||||
.error_at_line(CompilerError::FunctionNotFound(name.to_string())));
|
||||
|
|
@ -325,7 +330,7 @@ impl AsmPass {
|
|||
});
|
||||
let signature =
|
||||
lookup(&receiver_type, method_name).map_err(|e| self.error_at_line(e))?;
|
||||
if signature.arity() != arguments.len() as u8 {
|
||||
if signature.arity() != arguments.len() as u8 && !signature.has_varargs() {
|
||||
return Err(self.error_at_line(CompilerError::IllegalArgumentsException(
|
||||
format!("{}.{}", receiver_type, method_name),
|
||||
signature.parameters.len(),
|
||||
|
|
|
|||
|
|
@ -891,13 +891,24 @@ impl Parameter {
|
|||
pub fn new(name: impl Into<String>, value_type: TokenType) -> Self {
|
||||
Self {
|
||||
name: Token {
|
||||
token_type: TokenType::StringType,
|
||||
token_type: StringType,
|
||||
lexeme: name.into(),
|
||||
line: 0,
|
||||
},
|
||||
var_type: value_type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn varargs(token_type: TokenType) -> Self {
|
||||
Self {
|
||||
name: Token {
|
||||
token_type: StringType,
|
||||
lexeme: "varargs".into(),
|
||||
line: 0,
|
||||
},
|
||||
var_type: token_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mod tests {
|
|||
use crate::errors::CompilerErrorAtLine;
|
||||
use crate::errors::RuntimeError::{IllegalArgumentException, IndexOutOfBounds, NotSortable};
|
||||
use crate::errors::TipiLangError::{Compiler, Runtime};
|
||||
use crate::value::{Value, string, i64};
|
||||
use crate::value::{Value, i64, string};
|
||||
use chrono::DateTime;
|
||||
|
||||
#[test]
|
||||
|
|
@ -476,15 +476,30 @@ a"#)
|
|||
}
|
||||
// #[test]
|
||||
// fn package() {
|
||||
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));
|
||||
// assert_eq!(run(r#"a::b.c()"#), Ok(Value::U32(48)));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn guards() {
|
||||
// assert_eq!(
|
||||
// run(r#"fn get_all_users() -> list:
|
||||
// | /{uuid} -> service.get_by_uuid(uuid)?"#),
|
||||
// Ok(Value::Void)
|
||||
// );
|
||||
// }
|
||||
#[test]
|
||||
fn guards() {
|
||||
assert_eq!(
|
||||
run(r#"fn get_all_users() -> list:
|
||||
| /{uuid} -> service.get_by_uuid(uuid)?"#),
|
||||
Ok(Value::Void)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query() {
|
||||
let result =
|
||||
run(r#"sql("select id, first_name, last_name from customers where id = 1")"#).unwrap();
|
||||
if let Value::List(records) = result {
|
||||
assert_eq!(records.len(), 1);
|
||||
if let Value::Map(record) = records.get(0).unwrap() {
|
||||
assert_eq!(record.get(&string("id")).unwrap(), &i64(1));
|
||||
assert_eq!(record.get(&string("first_name")).unwrap(), &string("sander"));
|
||||
assert_eq!(record.get(&string("last_name")).unwrap(), &string("hautvast"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,14 @@ impl Scanner {
|
|||
}
|
||||
'#' => self.add_token(TokenType::Hash),
|
||||
'+' => self.add_token(TokenType::Plus),
|
||||
':' => self.add_token(TokenType::Colon),
|
||||
':' => {
|
||||
let t = if self.match_next(':') {
|
||||
TokenType::ColonColon
|
||||
} else {
|
||||
TokenType::Colon
|
||||
};
|
||||
self.add_token(t);
|
||||
}
|
||||
';' => println!("Warning: Ignoring semicolon at line {}", self.line),
|
||||
'*' => self.add_token(TokenType::Star),
|
||||
'!' => {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ pub enum TokenType {
|
|||
Bool,
|
||||
Char,
|
||||
Colon,
|
||||
ColonColon,
|
||||
Comma,
|
||||
DateTime,
|
||||
Dot,
|
||||
|
|
@ -113,6 +114,7 @@ impl fmt::Display for TokenType {
|
|||
TokenType::Pipe => write!(f, "|"),
|
||||
TokenType::BitXor => write!(f, "^"),
|
||||
TokenType::Colon => write!(f, ":"),
|
||||
TokenType::ColonColon => write!(f, "::"),
|
||||
TokenType::Comma => write!(f, ","),
|
||||
TokenType::FloatingPoint => write!(f, "float"),
|
||||
TokenType::MapType => write!(f, "map"),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ pub enum Value {
|
|||
ObjectType(Box<Object>),
|
||||
Error(String),
|
||||
Void,
|
||||
Uuid(String),
|
||||
}
|
||||
|
||||
pub(crate) fn string(v: impl Into<String>) -> Value {
|
||||
|
|
@ -217,6 +218,7 @@ impl Display for Value {
|
|||
Value::Map(map) => to_string(f, map),
|
||||
Value::Error(v) => write!(f, "{}", v),
|
||||
Value::Void => write!(f, "()"),
|
||||
Value::Uuid(v) => write!(f, "{}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue