finished yard

This commit is contained in:
Sven Vogel 2023-01-02 12:06:30 +01:00
parent a506f51f71
commit 1b62b0fc4e
11 changed files with 451 additions and 0 deletions

24
selib/math.yard Normal file
View File

@ -0,0 +1,24 @@
@pragma(once)
@feature(conv, math)
@author(Sven Vogel)
floor(x:rat) = rat {
to_rat(to_int(x))
}
round(x:rat) = rat {
to_rat(to_int(x + 0.5))
}
ceil(x:rat) = rat {
to_rat(to_int(x + 1.0))
}
fract(x:rat) = rat {
x - floor(x)
}
log(x:rat, b:rat) = rat {
log(x) / log(b)
}

52
src/builtin/mod.rs Normal file
View File

@ -0,0 +1,52 @@
/// module for builtin functons
/// and the SENI-module
use crate::{parser::data::{Declr, Func}, vmrt::Data};
use self::modules::Module;
pub mod modules;
type Function = &'static dyn Fn(&[Data]) -> Result<Option<Data>, ()>;
#[derive(Clone)]
pub struct BuiltinFun {
declr: Declr<'static>,
func: Function
}
impl BuiltinFun {
pub fn declr(&self) -> Declr<'static> {
self.declr.clone()
}
pub fn func(&self) -> crate::parser::data::Func<'static> {
Func {
expr: None,
is_builtin: true,
raw: None
}
}
pub fn get_function(&self) -> Function {
self.func
}
}
pub fn get_builtin_funs(mods: &[Module]) -> Vec<BuiltinFun> {
let mut funs = vec![
BuiltinFun {
declr: Declr::generate_builtin("say_hello", vec![], None),
func: &say_hello
},
];
funs.append(&mut modules::get_submodules(mods));
return funs;
}
fn say_hello(_args: &[Data]) -> Result<Option<Data>, ()> {
println!("hello!");
Ok(None)
}

View File

@ -0,0 +1,50 @@
use crate::{token::Prim, parser::data::{Declr}, vmrt::Data, builtin::BuiltinFun};
pub fn int_to_rat(args: &[Data]) -> Result<Option<Data>, ()> {
match args [0] {
Data::Int(val) => Ok(Some(Data::Rat(val as f64))),
_ => Err(())
}
}
pub fn rat_to_int(args: &[Data]) -> Result<Option<Data>, ()> {
match args[0] {
Data::Rat(val) => Ok(Some(Data::Int(val as i64))),
_ => Err(())
}
}
pub fn str_to_int(args: &[Data]) -> Result<Option<Data>, ()> {
match &args[0] {
Data::Str(val) => Ok(Some(Data::Int(val.parse().unwrap_or(0)))),
_ => Err(())
}
}
pub fn str_to_rat(args: &[Data]) -> Result<Option<Data>, ()> {
match &args[0] {
Data::Str(val) => Ok(Some(Data::Rat(val.parse().unwrap_or(0.0)))),
_ => Err(())
}
}
pub fn get_module_funs<'a>() -> Vec<crate::builtin::BuiltinFun> {
vec![
BuiltinFun {
declr: Declr::generate_builtin("to_rat", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &int_to_rat
},
BuiltinFun {
declr: Declr::generate_builtin("to_int", vec![("x", Prim::Rat)], Some(Prim::Int)),
func: &rat_to_int
},
BuiltinFun {
declr: Declr::generate_builtin("parse_int", vec![("text", Prim::Str)], Some(Prim::Int)),
func: &str_to_int
},
BuiltinFun {
declr: Declr::generate_builtin("parse_rat", vec![("text", Prim::Str)], Some(Prim::Rat)),
func: &str_to_rat
}
]
}

26
src/builtin/modules/io.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::{token::Prim, parser::data::{Declr}, vmrt::Data, builtin::BuiltinFun};
pub fn print(args: &[Data]) -> Result<Option<Data>, ()> {
let text = args[0].to_str()?;
print!("{}", text);
Ok(None)
}
pub fn println(args: &[Data]) -> Result<Option<Data>, ()> {
let text = args[0].to_str()?;
println!("{}", text);
Ok(None)
}
pub fn get_module_funs<'a>() -> Vec<crate::builtin::BuiltinFun> {
vec![
BuiltinFun {
declr: Declr::generate_builtin("print", vec![("text", Prim::Str)], None),
func: &print
},
BuiltinFun {
declr: Declr::generate_builtin("println", vec![("text", Prim::Str)], None),
func: &println
},
]
}

View File

@ -0,0 +1,57 @@
use crate::{token::Prim, parser::data::{Declr}, vmrt::Data, builtin::BuiltinFun};
pub fn cos(args: &[Data]) -> Result<Option<Data>, ()> {
Ok(Some(Data::Rat(args[0].to_float()?.cos())))
}
pub fn sin(args: &[Data]) -> Result<Option<Data>, ()> {
Ok(Some(Data::Rat(args[0].to_float()?.sin())))
}
pub fn tan(args: &[Data]) -> Result<Option<Data>, ()> {
Ok(Some(Data::Rat(args[0].to_float()?.tan())))
}
pub fn ln(args: &[Data]) -> Result<Option<Data>, ()> {
Ok(Some(Data::Rat(args[0].to_float()?.ln())))
}
pub fn sqrt(args: &[Data]) -> Result<Option<Data>, ()> {
Ok(Some(Data::Rat(args[0].to_float()?.sqrt())))
}
pub fn pow(args: &[Data]) -> Result<Option<Data>, ()> {
let x = args[0].to_float()?;
let y = args[1].to_float()?;
Ok(Some(Data::Rat(y.powf(x))))
}
pub fn get_module_funs<'a>() -> Vec<crate::builtin::BuiltinFun> {
vec![
BuiltinFun {
declr: Declr::generate_builtin("cos", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &cos
},
BuiltinFun {
declr: Declr::generate_builtin("pow", vec![("x", Prim::Rat), ("y", Prim::Rat)], Some(Prim::Rat)),
func: &pow
},
BuiltinFun {
declr: Declr::generate_builtin("sin", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &sin
},
BuiltinFun {
declr: Declr::generate_builtin("tan", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &tan
},
BuiltinFun {
declr: Declr::generate_builtin("ln", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &ln
},
BuiltinFun {
declr: Declr::generate_builtin("sqrt", vec![("x", Prim::Int)], Some(Prim::Rat)),
func: &sqrt
},
]
}

View File

@ -0,0 +1,47 @@
pub mod conv;
pub mod math;
pub mod io;
pub mod os;
#[derive(PartialEq, Eq)]
pub enum Module {
Conv,
Math,
IO,
OS,
}
impl Module {
pub fn from_list(text: &str) -> Vec<Module> {
let mut vec = vec![];
for word in text.split(',') {
match word.trim() {
"conv" => vec.push(Module::Conv),
"math" => vec.push(Module::Math),
"io" => vec.push(Module::IO),
"os" => vec.push(Module::OS),
_ => crate::message(crate::token::MessageType::Warning, format!("unknown module: `{}`", word))
}
}
vec
}
}
pub fn get_submodules<'a>(modules: &[Module]) -> Vec<super::BuiltinFun> {
let mut funs = vec![];
for module in modules {
match module {
Module::Conv => funs.append(&mut conv::get_module_funs()),
Module::Math => funs.append(&mut math::get_module_funs()),
Module::IO => funs.append(&mut io::get_module_funs()),
Module::OS => funs.append(&mut os::get_module_funs()),
}
}
funs
}

21
src/builtin/modules/os.rs Normal file
View File

@ -0,0 +1,21 @@
use crate::{token::Prim, parser::data::{Declr}, vmrt::Data, builtin::BuiltinFun};
pub fn get_os(_: &[Data]) -> Result<Option<Data>, ()> {
if cfg!(windows) {
return Ok(Some(Data::Str(String::from("Windows"))))
} else if cfg!(unix) {
return Ok(Some(Data::Str(String::from("UNIX"))))
}
Ok(None)
}
pub fn get_module_funs<'a>() -> Vec<crate::builtin::BuiltinFun> {
vec![
BuiltinFun {
declr: Declr::generate_builtin("get_os", vec![], Some(Prim::Str)),
func: &get_os
},
]
}

106
src/direct/mod.rs Normal file
View File

@ -0,0 +1,106 @@
use std::{collections::VecDeque};
use crate::{token::{Token}, builtin::modules::Module};
#[derive(Default)]
pub struct LangSpecs {
/// builtin modules for extra builtin functions
builtin_features: Vec<crate::builtin::modules::Module>,
lang_version: u32,
authors: Vec<String>,
embedded_files: Vec<String>,
}
impl LangSpecs {
pub fn features(&self) -> &[crate::builtin::modules::Module] {
&self.builtin_features
}
}
pub fn resolve_directives(tokens: &mut VecDeque<Token>) -> LangSpecs {
let mut specs = LangSpecs::default();
for token in tokens.iter() {
match token {
Token::CompilerDirective(text, _) => parse_directive(text, &mut specs),
_ => ()
}
}
// remove compiler directives from source
tokens.retain(|token| match token {
Token::CompilerDirective(_, _) => false,
_ => true
});
specs
}
static DIRECTIVE_REGEX_SRC: &'static str = concat!(
r"@feature\(((?:\s*[\w]+\s*,?)*)\)",
r"|@version\(\s*([0-9]{3})\s*\)",
r"|@author\((.*)\)",
r"|@embed\((.*)\)"
);
lazy_static::lazy_static! {
static ref DIRECTIVE_REGEX: regex::Regex = regex::Regex::new(DIRECTIVE_REGEX_SRC).unwrap();
}
pub fn from_list(text: &str) -> Vec<String> {
let mut vec = vec![];
for word in text.split(',') {
vec.push(String::from(word.trim()))
}
vec
}
fn parse_directive(text: &str, specs: &mut LangSpecs) {
for cap in DIRECTIVE_REGEX.captures_iter(text) {
let mut enumerator = cap.iter().enumerate();
loop {
let next = enumerator.next();
if next.is_none() {
break;
}
let (i, group) = next.unwrap();
// ignore first group as its the entire match,
// as well as the 1st group (= comments)
if i < 1 {
continue;
}
if let Some(mat) = group {
match i {
1 => {
specs.builtin_features.append(&mut Module::from_list(mat.as_str()));
return;
},
2 => {
specs.lang_version = mat.as_str().parse().unwrap();
return;
},
3 => {
specs.authors.push(String::from(mat.as_str()));
return;
},
4 => {
specs.embedded_files.append(&mut from_list(mat.as_str()));
crate::message(crate::token::MessageType::Warning, "Embed directive not working at current state");
return;
},
_ => crate::message(crate::token::MessageType::Warning, format!("unknown directive: `{}`", text)),
}
break;
}
}
}
crate::message(crate::token::MessageType::Warning, format!("unknown directive: `{}`", text));
}

2
src/seni/mod.rs Normal file
View File

@ -0,0 +1,2 @@
/// SENI - Standard Edition Native Interface (for rust)

31
src/srcio/mod.rs Normal file
View File

@ -0,0 +1,31 @@
use std::{fs};
pub struct CodeSrc {
_path: String,
src: String,
}
impl CodeSrc {
pub fn new(path: &String) -> Result<CodeSrc, String> {
Ok(Self {
_path: path.to_owned(),
src: Self::read_code(path)?,
})
}
fn read_code(path: &String) -> Result<String, String> {
let result = fs::read_to_string(path);
// read the source
if let Ok(src) = result {
return Ok(src);
}
Err(format!("unable to fetch source code from {}: {}", path, result.err().unwrap()))
}
pub fn code(&self) -> &String {
&self.src
}
}

35
test.yard Normal file
View File

@ -0,0 +1,35 @@
@feature(io)
@version(100)
@author(Sven Vogel)
// recursion!
fac(x:int) = int {
despite x != 1 {
yield 1;
}
yield fac(x - 1) * x
}
main() = int {
x = 0
loop {
until x > 9 {
despite x != 5 {
x = x + 1
cont
}
println(""..x);
x = x + 1
}
break
}
println(""..fract(456.3928));
yield 0
}