Implement core modules and initial interpreter setup for SLS Rust
This commit is contained in:
parent
b70634b450
commit
6f81cbdf15
|
|
@ -0,0 +1,6 @@
|
|||
use crate::types::Value;
|
||||
|
||||
/// Collection of builtin functions. This is a placeholder module.
|
||||
pub fn hello() -> Value {
|
||||
Value::Str("hello from builtin".to_string())
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SlsError {
|
||||
Runtime(String),
|
||||
Lexer(String),
|
||||
Io(String),
|
||||
}
|
||||
|
||||
impl std::error::Error for SlsError {}
|
||||
|
||||
impl fmt::Display for SlsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
SlsError::Runtime(s) => write!(f, "Runtime: {}", s),
|
||||
SlsError::Lexer(s) => write!(f, "Lexer: {}", s),
|
||||
SlsError::Io(s) => write!(f, "IO: {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
use crate::errors::SlsError;
|
||||
use std::fs;
|
||||
|
||||
pub struct SlsFile {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
impl SlsFile {
|
||||
pub fn open(path: impl Into<String>) -> Self {
|
||||
SlsFile { path: path.into() }
|
||||
}
|
||||
|
||||
pub fn read_all(&self) -> Result<String, SlsError> {
|
||||
fs::read_to_string(&self.path).map_err(|e| SlsError::Io(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
use std::collections::HashMap;
|
||||
use crate::types::Value;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct HashTable {
|
||||
pub map: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl HashTable {
|
||||
pub fn new() -> Self {
|
||||
HashTable { map: HashMap::new() }
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &str) -> Option<&Value> {
|
||||
self.map.get(key)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, key: String, val: Value) {
|
||||
self.map.insert(key, val);
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: &str) -> Option<Value> {
|
||||
self.map.remove(key)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
use crate::types::Value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Interpreter {
|
||||
pub globals: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new() -> Self {
|
||||
Interpreter { globals: HashMap::new() }
|
||||
}
|
||||
|
||||
/// Evaluate source and return a Value. This is a stubbed placeholder.
|
||||
pub fn eval(&mut self, _src: &str) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
Ok(Value::Nil)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Lexer {
|
||||
pub input: String,
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
impl Lexer {
|
||||
pub fn new(input: impl Into<String>) -> Self {
|
||||
Lexer { input: input.into(), pos: 0 }
|
||||
}
|
||||
|
||||
/// Stub: return next token as a string or None at EOF.
|
||||
pub fn next_token(&mut self) -> Option<String> {
|
||||
// placeholder for a real lexer implementation
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,24 @@
|
|||
mod types;
|
||||
mod errors;
|
||||
mod hash_table;
|
||||
mod sls_string;
|
||||
mod file;
|
||||
mod lexer;
|
||||
mod interpreter;
|
||||
mod repl;
|
||||
mod meta;
|
||||
mod builtin;
|
||||
|
||||
use crate::interpreter::Interpreter;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
println!("Starting sls (Rust) - {} v{}", meta::NAME, meta::VERSION);
|
||||
let mut interp = Interpreter::new();
|
||||
// placeholder: evaluate empty program to ensure basic startup
|
||||
match interp.eval("") {
|
||||
Ok(_) => println!("Interpreter initialized."),
|
||||
Err(e) => eprintln!("Interpreter failed to initialize: {}", e),
|
||||
}
|
||||
// start REPL stub
|
||||
repl::run_repl();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
pub const VERSION: &str = "0.1.0";
|
||||
pub const NAME: &str = "sls_rust";
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
use crate::interpreter::Interpreter;
|
||||
|
||||
pub fn run_repl() {
|
||||
let mut interp = Interpreter::new();
|
||||
println!("SLS REPL (stub). Type Ctrl+C to exit.");
|
||||
// For now just call eval once as a smoke test
|
||||
let _ = interp.eval("");
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
use crate::types::SlsStr;
|
||||
|
||||
pub fn from_str(s: &str) -> SlsStr {
|
||||
s.to_string()
|
||||
}
|
||||
|
||||
pub fn concat(a: &SlsStr, b: &SlsStr) -> SlsStr {
|
||||
let mut r = a.clone();
|
||||
r.push_str(b);
|
||||
r
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
pub type SlsStr = String;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Value {
|
||||
Nil,
|
||||
Bool(bool),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Str(SlsStr),
|
||||
Object(HashMap<String, Value>),
|
||||
Function(String),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn type_name(&self) -> &'static str {
|
||||
match self {
|
||||
Value::Nil => "nil",
|
||||
Value::Bool(_) => "bool",
|
||||
Value::Int(_) => "int",
|
||||
Value::Float(_) => "float",
|
||||
Value::Str(_) => "str",
|
||||
Value::Object(_) => "object",
|
||||
Value::Function(_) => "function",
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue