add sasm writing

This commit is contained in:
Daniella 2023-08-04 20:42:43 +02:00
parent c01d5adf63
commit b4c8593d41
Signed by: TudbuT
GPG key ID: 7D63D5634B7C417F
6 changed files with 271 additions and 5 deletions

5
assemble.spl Normal file
View file

@ -0,0 +1,5 @@
func main { mega | with args ;
2 args:get write-file-sasm println
0
}

9
echo.spl Normal file
View file

@ -0,0 +1,9 @@
func main { mega | with args ;
2 args:iter:skip =args
{ | with item ;
item print
" " print
} args:foreach
"\n" print
0 exit
}

View file

@ -62,6 +62,7 @@ fn read_block(str_words: &[String], isfn: bool) -> Result<(Option<u32>, Words, u
return Err(LexerError::FunctionBlockExpected);
}
}
// lambda
"{" => {
let block = read_block(&str_words[i..], true)?;
i += block.2;

View file

@ -1,6 +1,6 @@
use std::sync::Arc;
use std::{sync::Arc, time::SystemTime};
use crate::{Frame, Func, FuncImpl, Keyword, Value, Word, Words};
use crate::{Frame, Func, FuncImpl, FuncImplType, Keyword, Value, Word, Words};
/// Reads sasm, the text representation of an SPL AST.
pub fn sasm_read(s: String) -> Words {
@ -62,7 +62,7 @@ fn sasm_parse<'a>(line: &str, words: &mut Vec<Word>, lines: &mut impl Iterator<I
methods,
match iter.next() {
None => false,
Some(x) => (|x| x == "namespace")(x),
Some(x) => x == "namespace",
},
)))
}
@ -86,6 +86,33 @@ fn sasm_parse<'a>(line: &str, words: &mut Vec<Word>, lines: &mut impl Iterator<I
))),
"objpush" => words.push(Word::Key(Keyword::ObjPush)),
"objpop" => words.push(Word::Key(Keyword::ObjPop)),
"func_of_Rust" => {
// output += &format!(
// "func_of_{kind:?} {name} {t}\0\0{}\0\0end {t}\n",
// content.replace("\0", "\0\x01").replace("\n", "\0\0")
// );
let name = line[1];
let marker = line[2];
let mut s = String::new();
let mut line;
while (
line = lines.next().expect("sasm string without end marker"),
line,
)
.1
!= "end ".to_owned() + marker
{
s = s + line + "\n";
}
if let Some(l) = s.strip_suffix("\n") {
s = l.to_owned();
}
words.push(Word::Key(Keyword::FuncOf(
name.to_owned(),
s,
FuncImplType::Rust,
)));
}
// main words
"const" => match line[1] {
"str" => {
@ -181,3 +208,172 @@ fn sasm_parse<'a>(line: &str, words: &mut Vec<Word>, lines: &mut impl Iterator<I
_ => panic!("invalid sasm instruction: {}", line[0]),
}
}
pub fn sasm_write(words: Words) -> String {
sasm_write_func(words)
.replace("\0\0", "\n")
.replace("\0\x01", "\0")
}
fn sasm_write_func(words: Words) -> String {
let mut output = String::new();
for word in words.words {
match word {
Word::Key(word) => match word {
Keyword::Dump => {
output += "dump\n";
}
Keyword::Def(x) => {
output += "def ";
output += &x;
output += "\n";
}
Keyword::Func(name, returns, text) => {
output += &format!("func {name} {returns}\n\t");
let text = sasm_write_func(text).replace("\n", "\n\t");
let text = text.trim_end();
output += &text;
output += "\nend\n";
}
Keyword::Construct(name, vars, methods, is_namespace) => {
output += &format!("construct {name} ");
for var in vars {
output += &var;
output += " ";
}
output += ";";
for method in &methods {
output += " ";
output += &method.0;
output += " ";
output += &method.1 .0.to_string();
}
if is_namespace {
output += " ; namespace";
}
output += "\n";
for method in methods {
output += "\t";
output += &sasm_write_func(method.1 .1)
.replace("\n", "\n\t")
.trim_end();
output += "\nend\n";
}
}
Keyword::Include(type_to_include, t) => {
output += &format!("include {type_to_include} {t}\n");
}
Keyword::Use(path) => output += &format!("use {path}\n"),
Keyword::While(cond, blk) => {
output += "while\n\t";
output += &sasm_write_func(cond).replace("\n", "\n\t").trim_end();
output += "\nend\n\t";
output += &sasm_write_func(blk).replace("\n", "\n\t").trim_end();
output += "\nend\n";
}
Keyword::If(blk) => {
output += "if\n\t";
output += &sasm_write_func(blk).replace("\n", "\n\t").trim_end();
output += "\nend\n";
}
Keyword::With(items) => {
output += "with";
for item in items {
output += " ";
output += &item;
}
output += "\n";
}
Keyword::Catch(kinds, blk, ctch) => {
output += "catch";
for kind in kinds {
output += " ";
output += &kind;
}
output += "\n\t";
output += &sasm_write_func(blk).replace("\n", "\n\t").trim_end();
output += "\nend\n\t";
output += &sasm_write_func(ctch).replace("\n", "\n\t").trim_end();
output += "\nend\n";
}
Keyword::ObjPush => output += "objpush\n",
Keyword::ObjPop => output += "objpop\n",
Keyword::FuncOf(name, content, kind) => {
fn time() -> String {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_micros()
.to_string()
}
let mut t = time();
while content.contains(&t) {
t = time();
}
output += &format!(
"func_of_{kind:?} {name} {t}\0\0{}\0\0end {t}\n",
content.replace("\0", "\0\x01").replace("\n", "\0\0")
);
}
},
Word::Const(item) => match item {
Value::Null => output += "const null\n",
Value::Int(x) => output += &format!("const int {x}\n"),
Value::Long(x) => output += &format!("const long {x}\n"),
Value::Mega(x) => output += &format!("const mega {x}\n"),
Value::Float(x) => output += &format!("const float {x}\n"),
Value::Double(x) => output += &format!("const double {x}\n"),
Value::Func(x) => {
let text = match &x.to_call {
FuncImpl::Native(_) => panic!("sasm can't write native function"),
FuncImpl::NativeDyn(_) => panic!("sasm can't write native function"),
FuncImpl::SPL(x) => sasm_write_func(x.clone()).replace("\n", "\n\t"),
};
let text = text.trim_end();
output += &format!("const func {}\n\t{}\nend\n", x.ret_count, text);
}
Value::Array(_) => panic!("sasm can't write arrays"),
Value::Str(text) => {
fn time() -> String {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_micros()
.to_string()
}
let mut t = time();
while text.contains(&t) {
t = time();
}
output += &format!(
"const str {t}\0\0{}\0\0end {t}\n",
text.replace("\0", "\0\x01").replace("\n", "\0\0")
);
}
},
Word::Call(name, rem, ra) => {
output += "call ";
output += &name;
if rem {
output += " pop";
}
for _ in 0..ra {
output += " ref";
}
output += "\n";
}
Word::ObjCall(name, rem, ra) => {
output += "objcall ";
output += &name;
if rem {
output += " pop";
}
for _ in 0..ra {
output += " ref";
}
output += "\n";
}
}
}
output
}

View file

@ -9,7 +9,7 @@ use std::{
sync::Arc,
};
use crate::{dyn_fns, mutex::Mut, runtime::*, *};
use crate::{dyn_fns, mutex::Mut, runtime::*, sasm::sasm_write, *};
#[macro_export]
macro_rules! type_err {
@ -803,9 +803,37 @@ pub fn throw(stack: &mut Stack) -> OError {
stack.err(ErrorKind::CustomObject(obj))
}
pub fn write_sasm(stack: &mut Stack) -> OError {
require_on_stack!(code, Str, stack, "write-sasm");
stack.push(
Value::Str(
lexer::lex(code)
.map(|x| sasm_write(x))
.map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
)
.spl(),
);
Ok(())
}
pub fn write_file_sasm(stack: &mut Stack) -> OError {
require_on_stack!(file, Str, stack, "write-file-sasm");
stack.push(
Value::Str(
lexer::lex(
fs::read_to_string(file).map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?,
)
.map(|x| sasm_write(x))
.map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
)
.spl(),
);
Ok(())
}
pub fn register(r: &mut Stack, o: Arc<Frame>) {
type Fn = fn(&mut Stack) -> OError;
let fns: [(&str, Fn, u32); 51] = [
let fns: [(&str, Fn, u32); 53] = [
("pop", pop, 0),
("dup", dup, 2),
("clone", clone, 1),
@ -857,6 +885,8 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
("bytes-to-str", bytes_to_str, 1),
("acopy", acopy, 1),
("throw", throw, 0),
("write-sasm", write_sasm, 1),
("write-file-sasm", write_file_sasm, 1),
];
for f in fns {
r.define_func(

25
std.spl
View file

@ -133,6 +133,31 @@ construct _array-ext {
}
} include _array-ext in array
construct _func-ext {
args
;
call { | with this ;
this:args null eq if {
0 anew this:=args
}
this:args:to-stack this call
}
add-args { this | with args this ;
this:args null eq if {
0 anew this:=args
}
[ this:args:to-stack args:to-stack ] this:=args
this
}
add-arg { this | with arg this ;
this:args null eq if {
0 anew this:=args
}
[ this:args:to-stack arg ] this:=args
this
}
} include _func-ext in func
"#iter.spl" import
construct List {