Compare commits
2 Commits
08a8aadf16
...
a26a1c0d4a
| Author | SHA1 | Date |
|---|---|---|
|
|
a26a1c0d4a | |
|
|
08f0437136 |
|
|
@ -9,11 +9,11 @@ fn try_cmd(cmd: &mut Command) -> Option<String> {
|
||||||
Some(String::from_utf8_lossy(&out.stdout).trim().to_string())
|
Some(String::from_utf8_lossy(&out.stdout).trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() {
|
||||||
// Emit vergen default build info (BUILD_DATE / BUILD_TIME)
|
// Emit all default vergen build info (BUILD_DATE / BUILD_TIME, etc.)
|
||||||
EmitBuilder::builder().build()?;
|
EmitBuilder::builder().all_build();
|
||||||
|
|
||||||
// Git describe + commit date (exact match to your Python)
|
// Git describe + commit date (matches your Python logic)
|
||||||
let commit_info = (|| {
|
let commit_info = (|| {
|
||||||
let hash = try_cmd(
|
let hash = try_cmd(
|
||||||
Command::new("git")
|
Command::new("git")
|
||||||
|
|
@ -36,12 +36,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
println!("cargo:rustc-env=GIT_COMMIT_HASH={}", commit_info);
|
println!("cargo:rustc-env=GIT_COMMIT_HASH={}", commit_info);
|
||||||
|
|
||||||
// Compiler name and rustc version
|
// Compiler info
|
||||||
println!("cargo:rustc-env=COMPILER_NAME=rustc");
|
println!("cargo:rustc-env=COMPILER_NAME=rustc");
|
||||||
|
|
||||||
let rustc_ver = try_cmd(Command::new("rustc").arg("--version"))
|
let rustc_ver = try_cmd(Command::new("rustc").arg("--version"))
|
||||||
.unwrap_or_else(|| "unknown".into());
|
.unwrap_or_else(|| "unknown".into());
|
||||||
println!("cargo:rustc-env=COMPILER_VER={}", rustc_ver);
|
println!("cargo:rustc-env=COMPILER_VER={}", rustc_ver);
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,45 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
|
||||||
|
|
||||||
use crate::interpreter::InterpreterState;
|
use crate::interpreter::InterpreterState;
|
||||||
use crate::lexer::{LexerInfo, lexical_analysis};
|
use crate::lexer::{LexerInfo, lexical_analysis, LexResult};
|
||||||
use crate::string::SlsStr;
|
|
||||||
use crate::errors::{LexerResult, LexerTokenResult};
|
|
||||||
|
|
||||||
/// Execute the contents of a script file.
|
/// Execute the contents of a script file.
|
||||||
pub fn exec_file(interpreter: &mut InterpreterState, filename: SlsStr) -> bool {
|
pub fn exec_file(interpreter: &mut InterpreterState, filename: &str) -> bool {
|
||||||
// Read the whole file
|
// Read the whole file
|
||||||
let source = match fs::read_to_string(&filename.str) {
|
let source = match fs::read_to_string(filename) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Cannot read file: {} ({})", filename.str, e);
|
eprintln!("Cannot read file: {} ({})", filename, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap source in SlsStr
|
let mut lexer_info = LexerInfo::new(filename.clone(), source.clone());
|
||||||
let code = SlsStr::from_string(source);
|
|
||||||
let mut lexer_info = LexerInfo::new(filename.clone(), code);
|
|
||||||
|
|
||||||
let result = lexical_analysis(&mut lexer_info);
|
let result = lexical_analysis(&mut lexer_info);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
LexerResult::Error(err) => {
|
LexResult::Ok(tokens) => {
|
||||||
eprintln!("{}", err.message);
|
for token in tokens {
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
LexerResult::Ok(mut head) => {
|
|
||||||
let mut node = Some(head.as_mut());
|
|
||||||
while let Some(tok) = node {
|
|
||||||
match tok {
|
|
||||||
LexerTokenResult::Error(err) => {
|
|
||||||
eprintln!("{}", err.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LexerTokenResult::Token(token) => {
|
|
||||||
if !interpreter.execute(token) {
|
if !interpreter.execute(token) {
|
||||||
eprintln!("A runtime error occurred!");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
node = None; // No linked list, next handled below
|
|
||||||
}
|
|
||||||
LexerTokenResult::Next(_, next) => {
|
|
||||||
node = next.as_deref_mut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LexResult::Err(err) => {
|
||||||
|
eprintln!("{}", err.message);
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stand-alone file execution entry point.
|
/// Stand-alone file execution entry point.
|
||||||
pub fn run_file(filename: SlsStr) -> i32 {
|
pub fn run_file(filename: &str) -> i32 {
|
||||||
println!("Executing file: {}", filename.str);
|
println!("Executing file: {}", filename);
|
||||||
|
|
||||||
let mut interpreter = match InterpreterState::new() {
|
let mut interpreter = InterpreterState::new();
|
||||||
Some(i) => i,
|
|
||||||
None => return 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if exec_file(&mut interpreter, filename) {
|
if exec_file(&mut interpreter, filename) {
|
||||||
0
|
0
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ pub enum StackValue {
|
||||||
U16(u16),
|
U16(u16),
|
||||||
U8(u8),
|
U8(u8),
|
||||||
|
|
||||||
Float(f32),
|
F32(f32),
|
||||||
Double(f64),
|
F64(f64),
|
||||||
|
|
||||||
Character(u8),
|
Character(u8),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
|
@ -48,9 +48,8 @@ impl InterpreterState {
|
||||||
functions: HashMap::new(),
|
functions: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_token(state: &mut InterpreterState, token: Token) -> bool {
|
pub fn push_token(&mut self, token: Token) -> bool {
|
||||||
let value = match token {
|
let value = match token {
|
||||||
Token::Eof => return true,
|
Token::Eof => return true,
|
||||||
|
|
||||||
|
|
@ -68,8 +67,8 @@ pub fn push_token(state: &mut InterpreterState, token: Token) -> bool {
|
||||||
Token::U16(v) => StackValue::U16(v),
|
Token::U16(v) => StackValue::U16(v),
|
||||||
Token::U8(v) => StackValue::U8(v),
|
Token::U8(v) => StackValue::U8(v),
|
||||||
|
|
||||||
Token::Float(v) => StackValue::Float(v),
|
Token::Float(v) => StackValue::F32(v),
|
||||||
Token::Double(v) => StackValue::Double(v),
|
Token::Double(v) => StackValue::F64(v),
|
||||||
|
|
||||||
Token::Character(c) => StackValue::Character(c),
|
Token::Character(c) => StackValue::Character(c),
|
||||||
Token::Boolean(b) => StackValue::Boolean(b),
|
Token::Boolean(b) => StackValue::Boolean(b),
|
||||||
|
|
@ -81,46 +80,51 @@ pub fn push_token(state: &mut InterpreterState, token: Token) -> bool {
|
||||||
Token::TypeTuple(_) => return false,
|
Token::TypeTuple(_) => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
state.stack.push(value);
|
self.stack.push(value);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_func(state: &mut InterpreterState, key: &str) -> bool {
|
pub fn execute_func(&mut self, key: &str) -> bool {
|
||||||
let item = match state.functions.get(key) {
|
let item = match self.functions.get(key) {
|
||||||
Some(v) => v.clone(),
|
Some(v) => v.clone(),
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
FunctionItem::Builtin(f) => f(state),
|
FunctionItem::Builtin(f) => f(self),
|
||||||
FunctionItem::TokenString(ts) => execute_token_string(state, ts),
|
FunctionItem::TokenString(ts) => self.execute_token_string(ts),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_token_string(state: &mut InterpreterState, ts: TokenString) -> bool {
|
pub fn execute_token_string(&mut self, ts: TokenString) -> bool {
|
||||||
for token in ts.tokens {
|
for token in ts.tokens {
|
||||||
if let Token::Identifier(id) = &token {
|
if let Token::Identifier(id) = &token {
|
||||||
if !id.is_literal {
|
if !id.is_literal {
|
||||||
if !execute_func(state, &id.name) {
|
if !self.execute_func(&id.name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !push_token(state, token) {
|
if !self.push_token(token) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(state: &mut InterpreterState, token: Token) -> bool {
|
pub fn execute(&mut self, token: Token) -> bool {
|
||||||
match token {
|
match token {
|
||||||
Token::Identifier(id) if !id.is_literal => {
|
Token::Identifier(id) if !id.is_literal => {
|
||||||
execute_func(state, &id.name)
|
self.execute_func(&id.name)
|
||||||
}
|
}
|
||||||
_ => push_token(state, token),
|
_ => self.push_token(token),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stack_top(&self) -> Option<&StackValue> {
|
||||||
|
self.stack.get(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
mod builtin;
|
||||||
|
mod file;
|
||||||
|
mod interpreter;
|
||||||
|
mod lexer;
|
||||||
|
mod repl;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::file::run_file;
|
use file::run_file;
|
||||||
use crate::repl::repl;
|
use repl::repl;
|
||||||
use crate::string::SlsStr;
|
|
||||||
|
|
||||||
// These mirror the C macros.
|
// These mirror the C macros.
|
||||||
const SLS_NAME: &str = "SLS_RUST";
|
const SLS_NAME: &str = "SLS_RUST";
|
||||||
|
|
@ -14,20 +19,15 @@ const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH", "UNKNOWN");
|
||||||
const COMPILER_NAME: &str = env!("COMPILER_NAME", "Unknown");
|
const COMPILER_NAME: &str = env!("COMPILER_NAME", "Unknown");
|
||||||
const COMPILER_VER: &str = env!("COMPILER_VER", "0");
|
const COMPILER_VER: &str = env!("COMPILER_VER", "0");
|
||||||
|
|
||||||
fn print_version() {
|
pub fn print_version() {
|
||||||
println!(
|
let git_hash = option_env!("GIT_COMMIT_HASH").unwrap_or("unknown");
|
||||||
"YREA SLS ({}) {} ({})",
|
let compiler = option_env!("COMPILER_NAME").unwrap_or("rustc");
|
||||||
SLS_NAME,
|
let compiler_ver = option_env!("COMPILER_VER").unwrap_or("unknown");
|
||||||
SLS_VER,
|
let build_date = std::env::var("BUILD_DATE").unwrap_or_else(|_| "unknown".into());
|
||||||
GIT_COMMIT_HASH
|
let build_time = std::env::var("BUILD_TIME").unwrap_or_else(|_| "unknown".into());
|
||||||
);
|
|
||||||
println!(
|
println!("YREA SLS (SLS_RUST) a.0.0 ({git_hash})");
|
||||||
"Compiled with {} {} on {} {}",
|
println!("Compiled with {compiler} {compiler_ver} at {build_date} {build_time}");
|
||||||
COMPILER_NAME,
|
|
||||||
COMPILER_VER,
|
|
||||||
env!("BUILD_DATE"),
|
|
||||||
env!("BUILD_TIME")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
@ -58,8 +58,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(file) = filename {
|
if let Some(file) = filename {
|
||||||
let sls_filename = SlsStr::from_string(file);
|
let status = run_file(&file);
|
||||||
let status = run_file(sls_filename);
|
|
||||||
process::exit(status);
|
process::exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use crate::lexer::{Lexer, LexerInfo, lexical_analysis};
|
use crate::lexer::{LexerInfo, LexResult, lexical_analysis};
|
||||||
use crate::meta::print_version;
|
use crate::print_version;
|
||||||
use crate::interpreter::{InterpreterState, StackType};
|
use crate::interpreter::{InterpreterState, StackValue};
|
||||||
use crate::string::{SlsStr};
|
|
||||||
use crate::errors::{LexerTokenResult, LexerResult};
|
|
||||||
|
|
||||||
static REPL_FILE_NAME: &str = "<STDIN>";
|
static REPL_FILE_NAME: &str = "<STDIN>";
|
||||||
|
|
||||||
|
|
@ -14,28 +12,28 @@ fn print_top_of_stack(state: &InterpreterState) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
match &item.value {
|
match &item {
|
||||||
StackType::Identifier(id) => {
|
StackValue::Identifier(id) => {
|
||||||
println!("#0: ::{}", id.name);
|
println!("#0: ::{}", id.name);
|
||||||
}
|
}
|
||||||
StackType::I64(v) => println!("#0: {}", v),
|
StackValue::I64(v) => println!("#0: {}", v),
|
||||||
StackType::I32(v) => println!("#0: {}:i32", v),
|
StackValue::I32(v) => println!("#0: {}:i32", v),
|
||||||
StackType::I16(v) => println!("#0: {}:i16", v),
|
StackValue::I16(v) => println!("#0: {}:i16", v),
|
||||||
StackType::I8(v) => println!("#0: {}:i8", v),
|
StackValue::I8(v) => println!("#0: {}:i8", v),
|
||||||
|
|
||||||
StackType::U64(v) => println!("#0: {}:u64", v),
|
StackValue::U64(v) => println!("#0: {}:u64", v),
|
||||||
StackType::U32(v) => println!("#0: {}:u32", v),
|
StackValue::U32(v) => println!("#0: {}:u32", v),
|
||||||
StackType::U16(v) => println!("#0: {}:u16", v),
|
StackValue::U16(v) => println!("#0: {}:u16", v),
|
||||||
StackType::U8(v) => println!("#0: {}:u8", v),
|
StackValue::U8(v) => println!("#0: {}:u8", v),
|
||||||
|
|
||||||
StackType::F32(v) => println!("#0: {}:f32", v),
|
StackValue::F32(v) => println!("#0: {}:f32", v),
|
||||||
StackType::F64(v) => println!("#0: {}", v),
|
StackValue::F64(v) => println!("#0: {}", v),
|
||||||
|
|
||||||
StackType::Character(ch) => println!("#0: {}", ch),
|
StackValue::Character(ch) => println!("#0: {}", ch),
|
||||||
StackType::Boolean(b) => println!("#0: {}", if *b { "TRUE" } else { "FALSE" }),
|
StackValue::Boolean(b) => println!("#0: {}", if *b { "TRUE" } else { "FALSE" }),
|
||||||
|
|
||||||
StackType::TokenString(_) => println!("#0: <TOKEN STRING>"),
|
StackValue::TokenString(_) => println!("#0: <TOKEN STRING>"),
|
||||||
StackType::Callable(_) => println!("#0: <CALLABLE>"),
|
StackValue::Callable(_) => println!("#0: <CALLABLE>"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,10 +43,7 @@ pub fn repl() -> i32 {
|
||||||
println!("Type `#exit` to exit.");
|
println!("Type `#exit` to exit.");
|
||||||
io::stdout().flush().unwrap();
|
io::stdout().flush().unwrap();
|
||||||
|
|
||||||
let mut interpreter = match InterpreterState::new() {
|
let mut interpreter = InterpreterState::new();
|
||||||
Some(i) => i,
|
|
||||||
None => return 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
@ -64,41 +59,24 @@ pub fn repl() -> i32 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let code = SlsStr::from_string(buf.clone());
|
let code = buf.clone();
|
||||||
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME.into(), code.clone());
|
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME, code.clone());
|
||||||
let result = lexical_analysis(&mut lexer_info);
|
let result = lexical_analysis(&mut lexer_info);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
LexerResult::Error(err) => {
|
LexResult::Ok(tokens) => {
|
||||||
println!("{}", err.message);
|
for token in tokens {
|
||||||
|
if !interpreter.execute(token) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LexerResult::Ok(mut head) => {
|
|
||||||
let mut node = Some(head.as_mut());
|
|
||||||
|
|
||||||
while let Some(tok_node) = node {
|
|
||||||
match tok_node {
|
|
||||||
LexerTokenResult::Error(err) => {
|
|
||||||
println!("{}", err.message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LexerTokenResult::Token(tok) => {
|
|
||||||
if !interpreter.execute(tok) {
|
|
||||||
println!("A runtime error occurred!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LexerTokenResult::Next(_, next) => {
|
|
||||||
node = next.as_deref_mut();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_top_of_stack(&interpreter);
|
print_top_of_stack(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LexResult::Err(err) => {
|
||||||
|
println!("{}", err.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue