1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use crate::vmbindings::vm::Vm;
use crate::vmbindings::vmerror::VmError;
use crate::vmbindings::record::Record;
use crate::vmbindings::value::*;
use crate::vmbindings::gc::{Gc, ref_inc};

mod io;
mod eval;
mod math;
mod file;
mod cmd;
mod env;
mod time;

mod array;
mod string;
mod int;
mod float;
mod record;

pub struct HanayoCtx {
    pub file_rec: Gc<Record>,
    pub cmd_rec: Gc<Record>,
    pub time_rec: Gc<Record>,
}

pub fn init(vm : &mut Vm) {
    let globalenv = unsafe { &mut *vm.globalenv };
    macro_rules! set_var {
        ($x:literal, $y:expr) => (globalenv.insert($x.to_string(), $y.wrap()));
    }
    macro_rules! set_obj_var {
        ($o: expr, $x:literal, $y:expr) => ($o.as_mut().insert($x.to_string(), $y.wrap()));
    }
    // constants
    set_var!("nil", Value::Nil);
    set_var!("true", Value::Int(1));
    set_var!("false", Value::Int(0));
    set_var!("inf", Value::Float(std::f64::INFINITY));
    set_var!("nan", Value::Float(std::f64::NAN));

    // builtin functions
    set_var!("print", Value::NativeFn(io::print));
    set_var!("input", Value::NativeFn(io::input));
    set_var!("eval", Value::NativeFn(eval::eval));

    // maths
    set_var!("sqrt", Value::NativeFn(math::sqrt));

    // #region array
    {
    let mut array = Gc::new(Record::new());
    set_obj_var!(array, "constructor", Value::NativeFn(array::constructor));
    set_obj_var!(array, "length",      Value::NativeFn(array::length));
    set_obj_var!(array, "insert!",     Value::NativeFn(array::insert_));
    set_obj_var!(array, "delete!",     Value::NativeFn(array::delete_));
    set_obj_var!(array, "push",        Value::NativeFn(array::push));
    set_obj_var!(array, "pop",         Value::NativeFn(array::pop));
    set_obj_var!(array, "sort",        Value::NativeFn(array::sort));
    set_obj_var!(array, "sort!",       Value::NativeFn(array::sort_));
    set_obj_var!(array, "map",         Value::NativeFn(array::map));
    set_obj_var!(array, "filter",      Value::NativeFn(array::filter));
    set_obj_var!(array, "reduce",      Value::NativeFn(array::reduce));
    set_obj_var!(array, "index",       Value::NativeFn(array::index));
    set_obj_var!(array, "join",        Value::NativeFn(array::join));
    vm.darray = array.to_mut_raw(); unsafe { ref_inc(vm.darray as *mut libc::c_void); }
    set_var!("Array", Value::Record(array));
    }
    // #endregion

    // #region string
    {
    let mut string = Gc::new(Record::new());
    set_obj_var!(string, "constructor", Value::NativeFn(string::constructor));
    set_obj_var!(string, "length",      Value::NativeFn(string::length));
    set_obj_var!(string, "bytesize",    Value::NativeFn(string::bytesize));
    set_obj_var!(string, "startswith?", Value::NativeFn(string::startswith));
    set_obj_var!(string, "endswith?",   Value::NativeFn(string::endswith));
    set_obj_var!(string, "delete",      Value::NativeFn(string::delete));
    set_obj_var!(string, "delete!",     Value::NativeFn(string::delete_));
    set_obj_var!(string, "copy",        Value::NativeFn(string::copy));
    set_obj_var!(string, "insert!",     Value::NativeFn(string::insert_));
    set_obj_var!(string, "split",       Value::NativeFn(string::split));
    set_obj_var!(string, "index",       Value::NativeFn(string::index));
    set_obj_var!(string, "chars",       Value::NativeFn(string::chars));
    set_obj_var!(string, "ord",         Value::NativeFn(string::ord));
    vm.dstr = string.to_mut_raw(); unsafe { ref_inc(vm.dstr as *mut libc::c_void); }
    set_var!("String", Value::Record(string));
    }
    // #endregion

    // #region int
    {
    let mut int = Gc::new(Record::new());
    set_obj_var!(int, "constructor", Value::NativeFn(int::constructor));
    set_obj_var!(int, "chr",         Value::NativeFn(int::chr));
    vm.dint = int.to_mut_raw(); unsafe { ref_inc(vm.dint as *mut libc::c_void); }
    set_var!("Int", Value::Record(int));
    }
    // #endregion

    // #region float
    {
    let mut float = Gc::new(Record::new());
    set_obj_var!(float, "constructor", Value::NativeFn(float::constructor));
    vm.dfloat = float.to_mut_raw(); unsafe { ref_inc(vm.dfloat as *mut libc::c_void); }
    set_var!("Float", Value::Record(float));
    }
    // #endregion

    // #region record
    {
    let mut record = Gc::new(Record::new());
    set_obj_var!(record, "constructor", Value::NativeFn(record::constructor));
    set_obj_var!(record, "keys",        Value::NativeFn(record::keys));
    vm.drec = record.to_mut_raw(); unsafe { ref_inc(vm.drec as *mut libc::c_void); }
    set_var!("Record", Value::Record(record));
    }
    // #endregion

    // #region files
    let file = Gc::new(Record::new());
    set_obj_var!(file, "constructor", Value::NativeFn(file::constructor));
    set_obj_var!(file, "close",       Value::NativeFn(file::close));
    set_obj_var!(file, "read",        Value::NativeFn(file::read));
    set_obj_var!(file, "read_up_to",  Value::NativeFn(file::read_up_to));
    set_obj_var!(file, "write",       Value::NativeFn(file::write));
    set_obj_var!(file, "seek",        Value::NativeFn(file::seek));
    set_obj_var!(file, "seek_from_start", Value::NativeFn(file::seek_from_start));
    set_obj_var!(file, "seek_from_end",   Value::NativeFn(file::seek_from_end));
    set_var!("File", Value::Record(file.clone()));
    // #endregion

    // #region cmd
    let cmd = Gc::new(Record::new());
    set_obj_var!(cmd, "constructor",  Value::NativeFn(cmd::constructor));
    set_obj_var!(cmd, "in" ,          Value::NativeFn(cmd::in_));
    set_obj_var!(cmd, "out",          Value::NativeFn(cmd::out));
    set_obj_var!(cmd, "err",          Value::NativeFn(cmd::err));
    set_obj_var!(cmd, "outputs",      Value::NativeFn(cmd::outputs));
    set_var!("Cmd", Value::Record(cmd.clone()));
    // #endregion

    // #region env
    let env = Gc::new(Record::new());
    set_obj_var!(env, "get",  Value::NativeFn(env::get));
    set_obj_var!(env, "set",  Value::NativeFn(env::set));
    set_obj_var!(env, "vars", Value::NativeFn(env::vars));
    set_var!("Env", Value::Record(env.clone()));
    // #endregion

    // #region time
    let time = Gc::new(Record::new());
    set_obj_var!(time, "constructor",  Value::NativeFn(time::constructor));
    set_obj_var!(time, "sleep",        Value::NativeFn(time::sleep));
    set_obj_var!(time, "since",        Value::NativeFn(time::since));
    set_obj_var!(time, "secs",         Value::NativeFn(time::secs));
    set_obj_var!(time, "millis",       Value::NativeFn(time::millis));
    set_obj_var!(time, "micros",       Value::NativeFn(time::micros));
    set_obj_var!(time, "nanos",        Value::NativeFn(time::nanos));
    set_var!("Time", Value::Record(time.clone()));
    // #endregion

    vm.stdlib = Some(HanayoCtx {
        file_rec: file,
        cmd_rec: cmd,
        time_rec: time
    });

}