all clippys done
This commit is contained in:
parent
07b7dd0337
commit
0e919983bd
13 changed files with 117 additions and 158 deletions
|
|
@ -14,9 +14,9 @@ use crate::tokens::TokenType::{
|
|||
};
|
||||
use crate::tokens::{Token, TokenType};
|
||||
use crate::value::Value;
|
||||
use crate::{Expr, Stmt, SymbolTable};
|
||||
use log::debug;
|
||||
use std::collections::HashMap;
|
||||
use crate::{Expr, Stmt, SymbolTable};
|
||||
|
||||
pub fn compile(
|
||||
path: Option<&str>,
|
||||
|
|
@ -109,7 +109,7 @@ impl AstCompiler {
|
|||
Err(self.raise(UnexpectedIndent(indent_on_line, expected_indent)))
|
||||
} else if indent_on_line < expected_indent {
|
||||
self.indent.pop();
|
||||
return Ok(None);
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(self.declaration(symbol_table)?))
|
||||
}
|
||||
|
|
@ -139,13 +139,13 @@ impl AstCompiler {
|
|||
}
|
||||
|
||||
fn guard_if_expr(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||
while !self.check(&SingleRightArrow) {
|
||||
if self.match_token(&[Slash]) {
|
||||
return self.path_guard_expr();
|
||||
if !self.check(&SingleRightArrow) {
|
||||
return if self.match_token(&[Slash]) {
|
||||
self.path_guard_expr()
|
||||
} else if self.match_token(&[TokenType::Question]) {
|
||||
return self.query_guard_expr(symbol_table);
|
||||
self.query_guard_expr(symbol_table)
|
||||
} else {
|
||||
return Err(self.raise(Expected("-> or ?")));
|
||||
Err(self.raise(Expected("-> or ?")))
|
||||
}
|
||||
}
|
||||
Ok(Stop {
|
||||
|
|
@ -408,7 +408,7 @@ impl AstCompiler {
|
|||
mut expr: Expression,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> Expr {
|
||||
while self.match_token(&types) {
|
||||
while self.match_token(types) {
|
||||
let operator = self.previous().clone();
|
||||
let right = self.comparison(symbol_table)?;
|
||||
expr = Expression::Binary {
|
||||
|
|
@ -431,8 +431,7 @@ impl AstCompiler {
|
|||
right: Box::new(right),
|
||||
})
|
||||
} else {
|
||||
let expr = self.get(symbol_table);
|
||||
expr
|
||||
self.get(symbol_table)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -541,7 +540,7 @@ impl AstCompiler {
|
|||
line: self.peek().line,
|
||||
literaltype: Integer,
|
||||
value: Value::U32(
|
||||
u32::from_str_radix(&self.previous().lexeme.trim_start_matches("0x"), 16)
|
||||
u32::from_str_radix(self.previous().lexeme.trim_start_matches("0x"), 16)
|
||||
.map_err(|e| self.raise(ParseError(format!("{:?}", e))))?,
|
||||
),
|
||||
}
|
||||
|
|
@ -550,7 +549,7 @@ impl AstCompiler {
|
|||
line: self.peek().line,
|
||||
literaltype: Integer,
|
||||
value: Value::U64(
|
||||
u64::from_str_radix(&self.previous().lexeme.trim_start_matches("0x"), 16)
|
||||
u64::from_str_radix(self.previous().lexeme.trim_start_matches("0x"), 16)
|
||||
.map_err(|e| self.raise(ParseError(format!("{:?}", e))))?,
|
||||
),
|
||||
}
|
||||
|
|
@ -747,7 +746,7 @@ impl AstCompiler {
|
|||
if !self.is_at_end() {
|
||||
self.current += 1;
|
||||
}
|
||||
&self.previous()
|
||||
self.previous()
|
||||
}
|
||||
|
||||
fn is_at_end(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
use crate::value::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
use crate::builtins::string::string_methods;
|
||||
use crate::errors::RuntimeError;
|
||||
|
||||
pub(crate) type MethodFn = fn(Value, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||
pub(crate) type MethodMap = HashMap<String, MethodFn>;
|
||||
pub(crate) type MethodTable = HashMap<String, MethodMap>;
|
||||
|
||||
const METHODS: LazyLock<MethodTable> = LazyLock::new(|| {
|
||||
let mut table: MethodTable = HashMap::new();
|
||||
table.insert("string".to_string(), string_methods());
|
||||
table
|
||||
});
|
||||
|
||||
pub(crate) fn insert(m: &mut MethodMap, name: &str, method: MethodFn) {
|
||||
m.insert(name.to_string(), method);
|
||||
}
|
||||
|
||||
pub fn call_builtin(
|
||||
type_name: &str,
|
||||
method_name: &str,
|
||||
self_val: Value,
|
||||
args: Vec<Value>,
|
||||
) -> Result<Value, RuntimeError> {
|
||||
METHODS
|
||||
.get(type_name)
|
||||
.and_then(|methods| methods.get(method_name))
|
||||
.ok_or_else(|| RuntimeError::FunctionNotFound(format!("{}.{}",type_name, method_name)))?
|
||||
(self_val, args)
|
||||
}
|
||||
|
||||
|
|
@ -1,2 +1,35 @@
|
|||
pub mod builtin_functions;
|
||||
mod string;
|
||||
|
||||
use crate::value::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
use crate::builtins::string::string_methods;
|
||||
use crate::errors::RuntimeError;
|
||||
|
||||
pub(crate) type MethodFn = fn(Value, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||
pub(crate) type MethodMap = HashMap<String, MethodFn>;
|
||||
pub(crate) type MethodTable = HashMap<String, MethodMap>;
|
||||
|
||||
static METHODS: LazyLock<MethodTable> = LazyLock::new(|| {
|
||||
let mut table: MethodTable = HashMap::new();
|
||||
table.insert("string".to_string(), string_methods());
|
||||
table
|
||||
});
|
||||
|
||||
pub(crate) fn insert(m: &mut MethodMap, name: &str, method: MethodFn) {
|
||||
m.insert(name.to_string(), method);
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
type_name: &str,
|
||||
method_name: &str,
|
||||
self_val: Value,
|
||||
args: Vec<Value>,
|
||||
) -> Result<Value, RuntimeError> {
|
||||
METHODS
|
||||
.get(type_name)
|
||||
.and_then(|methods| methods.get(method_name))
|
||||
.ok_or_else(|| RuntimeError::FunctionNotFound(format!("{}.{}",type_name, method_name)))?
|
||||
(self_val, args)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use crate::builtins::builtin_functions::{insert, MethodMap};
|
||||
use crate::builtins::{insert, MethodMap};
|
||||
use crate::errors::RuntimeError;
|
||||
use crate::value::Value;
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ impl Compiler {
|
|||
} => {
|
||||
let name_index = self
|
||||
.chunk
|
||||
.find_constant(&name)
|
||||
.find_constant(name)
|
||||
.unwrap_or_else(|| self.chunk.add_constant(Value::String(name.to_string())));
|
||||
let function = symbols.get(name);
|
||||
match function {
|
||||
|
|
@ -207,7 +207,7 @@ impl Compiler {
|
|||
.find_constant(&receiver_type)
|
||||
.unwrap_or_else(|| self.chunk.add_constant(Value::String(receiver_type)));
|
||||
|
||||
let name_index = self.chunk.find_constant(&method_name).unwrap_or_else(|| {
|
||||
let name_index = self.chunk.find_constant(method_name).unwrap_or_else(|| {
|
||||
self.chunk
|
||||
.add_constant(Value::String(method_name.to_string()))
|
||||
});
|
||||
|
|
|
|||
18
src/chunk.rs
18
src/chunk.rs
|
|
@ -1,13 +1,13 @@
|
|||
use std::collections::HashMap;
|
||||
use crate::ast_compiler::Parameter;
|
||||
use crate::tokens::TokenType;
|
||||
use crate::value::Value;
|
||||
use crate::vm::{
|
||||
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_F32,
|
||||
OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_STRING, OP_DEFINE, OP_DIVIDE, OP_EQUAL,
|
||||
OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT,
|
||||
OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT, OP_DEF_MAP,
|
||||
OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, OP_DEFINE,
|
||||
OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY,
|
||||
OP_NEGATE, OP_NOT, OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Chunk {
|
||||
|
|
@ -17,18 +17,18 @@ pub struct Chunk {
|
|||
lines: Vec<usize>,
|
||||
pub(crate) object_defs: HashMap<String, Vec<Parameter>>,
|
||||
pub(crate) function_parameters: Vec<Parameter>,
|
||||
pub vars: Vec<(TokenType, String)>
|
||||
pub vars: Vec<(TokenType, String)>,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub(crate) fn find_constant(&self, p0: &String) -> Option<usize> {
|
||||
for (i, constant) in self.constants.iter().enumerate() {
|
||||
if let Value::String(s) = constant {
|
||||
if s == p0 {
|
||||
if let Value::String(s) = constant
|
||||
&& s == p0
|
||||
{
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ impl Chunk {
|
|||
lines: vec![],
|
||||
object_defs: HashMap::new(),
|
||||
function_parameters: vec![],
|
||||
vars: vec![]
|
||||
vars: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub fn start_watch_daemon(source: &str, registry: Arc<ArcSwap<HashMap<String, Ch
|
|||
let start = SystemTime::now();
|
||||
loop {
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
if let Ok(_) = rx.recv() {
|
||||
if rx.recv().is_ok() {
|
||||
file_changed = true;
|
||||
}
|
||||
if file_changed && SystemTime::now().duration_since(start).unwrap() > ONE_SEC {
|
||||
|
|
|
|||
10
src/lib.rs
10
src/lib.rs
|
|
@ -4,12 +4,8 @@ use crate::errors::CrudLangError::Platform;
|
|||
use crate::errors::{CompilerErrorAtLine, CrudLangError};
|
||||
use crate::scanner::scan;
|
||||
use crate::symbol_builder::Symbol;
|
||||
use crate::value::Value;
|
||||
use crate::vm::interpret;
|
||||
use arc_swap::ArcSwap;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub mod ast_compiler;
|
||||
|
|
@ -89,13 +85,13 @@ pub fn compile(src: &str) -> Result<HashMap<String, Chunk>, CrudLangError> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn run(src: &str) -> Result<Value, CrudLangError> {
|
||||
pub(crate) fn run(src: &str) -> Result<value::Value, CrudLangError> {
|
||||
let tokens = scan(src)?;
|
||||
let mut symbol_table = HashMap::new();
|
||||
let ast = ast_compiler::compile(None, tokens, &mut symbol_table)?;
|
||||
symbol_builder::build("", &ast, &mut symbol_table);
|
||||
let mut registry = HashMap::new();
|
||||
bytecode_compiler::compile(None, &ast, &symbol_table, &mut registry)?;
|
||||
let registry = ArcSwap::from(Arc::new(registry));
|
||||
interpret(registry.load(), "main").map_err(CrudLangError::from)
|
||||
let registry = arc_swap::ArcSwap::from(std::sync::Arc::new(registry));
|
||||
vm::interpret(registry.load(), "main").map_err(CrudLangError::from)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ use axum::{Json, Router};
|
|||
use clap::Parser;
|
||||
use crudlang::chunk::Chunk;
|
||||
use crudlang::errors::CrudLangError;
|
||||
use crudlang::errors::CrudLangError::Platform;
|
||||
use crudlang::vm::interpret_async;
|
||||
use crudlang::{compile_sourcedir, map_underlying};
|
||||
use notify::Watcher;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use arc_swap::ArcSwap;
|
||||
use log::{debug, info};
|
||||
use log::info;
|
||||
|
||||
/// A simple CLI tool to greet users
|
||||
#[derive(Parser, Debug)]
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudL
|
|||
_ => {
|
||||
let registry_copy = registry.load().clone();
|
||||
let mut registry_copy = registry_copy.deref().clone();
|
||||
match recompile(&input, &mut registry_copy){
|
||||
match recompile(input, &mut registry_copy){
|
||||
Ok(_)=> {
|
||||
registry.store(Arc::new(registry_copy));
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl Scanner {
|
|||
_ => {
|
||||
if c == '0' && self.peek() == 'x' {
|
||||
self.hex_number()?;
|
||||
} else if is_digit(c) {
|
||||
} else if c.is_ascii_digit() {
|
||||
self.number();
|
||||
} else if is_alpha(c) {
|
||||
self.identifier();
|
||||
|
|
@ -167,7 +167,7 @@ impl Scanner {
|
|||
fn hex_number(&mut self) -> Result<(), CompilerErrorAtLine> {
|
||||
self.advance();
|
||||
self.advance();
|
||||
while is_digit(self.peek()) || is_alpha(self.peek()) {
|
||||
while self.peek().is_ascii_hexdigit() {
|
||||
self.advance();
|
||||
}
|
||||
let value: String = self.chars[self.start..self.current].iter().collect();
|
||||
|
|
@ -182,11 +182,11 @@ impl Scanner {
|
|||
}
|
||||
|
||||
fn number(&mut self) {
|
||||
while is_digit(self.peek()) {
|
||||
while self.peek().is_ascii_digit() {
|
||||
self.advance();
|
||||
}
|
||||
let mut has_dot = false;
|
||||
if self.peek() == '.' && is_digit(self.peek_next()) {
|
||||
if self.peek() == '.' && self.peek_next().is_ascii_digit() {
|
||||
has_dot = true;
|
||||
self.advance();
|
||||
}
|
||||
|
|
@ -269,9 +269,7 @@ impl Scanner {
|
|||
}
|
||||
|
||||
fn match_next(&mut self, expected: char) -> bool {
|
||||
if self.is_at_end() {
|
||||
false
|
||||
} else if self.chars[self.current] != expected {
|
||||
if self.is_at_end() || self.chars[self.current] != expected{
|
||||
false
|
||||
} else {
|
||||
self.current += 1;
|
||||
|
|
@ -306,20 +304,19 @@ struct Scanner {
|
|||
new_line: bool,
|
||||
}
|
||||
|
||||
fn is_digit(c: char) -> bool {
|
||||
c >= '0' && c <= '9'
|
||||
}
|
||||
|
||||
fn is_digit_or_scientific(c: char) -> bool {
|
||||
is_digit(c) || c == 'e' || c == 'E'
|
||||
c.is_ascii_digit() || c == 'e' || c == 'E'
|
||||
}
|
||||
|
||||
fn is_alphanumeric(c: char) -> bool {
|
||||
is_alpha(c) || is_digit(c)
|
||||
is_alpha(c) || c.is_ascii_digit()
|
||||
}
|
||||
|
||||
fn is_alpha(c: char) -> bool {
|
||||
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$'
|
||||
// (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$'
|
||||
// ('a'..='z').contains(&c) || ('A'..='Z').contains(&c) || c == '_' || c == '$'
|
||||
c.is_ascii_lowercase() || c.is_ascii_uppercase() || c == '_' || c == '$'
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -70,31 +70,6 @@ pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol
|
|||
}
|
||||
}
|
||||
|
||||
pub fn _add_types(
|
||||
path: &str,
|
||||
ast: &[Statement],
|
||||
symbols: &mut HashMap<String, Symbol>,
|
||||
) -> Result<(), CompilerError> {
|
||||
for statement in ast {
|
||||
match statement {
|
||||
Statement::VarStmt {
|
||||
name,
|
||||
var_type,
|
||||
initializer,
|
||||
} => {
|
||||
let inferred_type = infer_type(initializer, symbols);
|
||||
let calculated_type = calculate_type(var_type, &inferred_type)?;
|
||||
let entry = symbols.get_mut(&format!("{}.{}", path, name.lexeme));
|
||||
if let Some(Symbol::Variable { var_type, .. }) = entry {
|
||||
*var_type = calculated_type;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn calculate_type(
|
||||
declared_type: &TokenType,
|
||||
inferred_type: &TokenType,
|
||||
|
|
@ -157,8 +132,7 @@ pub fn infer_type(expr: &Expression, symbols: &HashMap<String, Symbol>) -> Token
|
|||
Integer => I64,
|
||||
_ => left_type,
|
||||
}
|
||||
} else {
|
||||
if let Plus = operator.token_type {
|
||||
} else if let Plus = operator.token_type {
|
||||
// includes string concatenation with numbers
|
||||
// followed by type coercion to 64 bits for numeric types
|
||||
debug!("coerce {} : {}", left_type, right_type);
|
||||
|
|
@ -195,7 +169,6 @@ pub fn infer_type(expr: &Expression, symbols: &HashMap<String, Symbol>) -> Token
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::Grouping { expression, .. } => infer_type(expression, symbols),
|
||||
Expression::Literal { literaltype, .. } => literaltype.clone(),
|
||||
Expression::List { literaltype, .. } => literaltype.clone(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use arc_swap::Guard;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
use crate::builtins::builtin_functions::call_builtin;
|
||||
|
||||
pub struct Vm {
|
||||
ip: usize,
|
||||
|
|
@ -206,17 +205,14 @@ impl Vm {
|
|||
let receiver_type_name = chunk.constants[function_type_index].to_string();
|
||||
|
||||
let receiver = self.pop();
|
||||
|
||||
let num_args = self.read(chunk);
|
||||
|
||||
let mut args = vec![];
|
||||
for _ in 0..num_args {
|
||||
let arg = self.pop();
|
||||
args.push(arg);
|
||||
}
|
||||
args.reverse();
|
||||
|
||||
let return_value = call_builtin(&receiver_type_name, &function_name, receiver, args)?;
|
||||
let return_value = crate::builtins::call(&receiver_type_name, &function_name, receiver, args)?;
|
||||
self.push(return_value);
|
||||
}
|
||||
OP_CALL => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue