add sasm writing
This commit is contained in:
parent
c01d5adf63
commit
b4c8593d41
6 changed files with 271 additions and 5 deletions
5
assemble.spl
Normal file
5
assemble.spl
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
func main { mega | with args ;
|
||||
2 args:get write-file-sasm println
|
||||
0
|
||||
}
|
9
echo.spl
Normal file
9
echo.spl
Normal 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
|
||||
}
|
|
@ -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;
|
||||
|
|
202
src/sasm.rs
202
src/sasm.rs
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
25
std.spl
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue