Browse Source

Gene implementation

Inderjit Gill 6 months ago
parent
commit
d9d1b8f079

+ 53
- 17
client/sen-client/src/lib.rs View File

@@ -20,9 +20,7 @@ mod utils;
20 20
 use cfg_if::cfg_if;
21 21
 use wasm_bindgen::prelude::*;
22 22
 
23
-// use sen_core::sen_parse;
24 23
 use sen_core;
25
-use sen_core::vm::{Vm, Env};
26 24
 
27 25
 cfg_if! {
28 26
     // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
@@ -43,13 +41,18 @@ extern "C" {
43 41
 #[wasm_bindgen]
44 42
 #[derive(Default)]
45 43
 pub struct Bridge {
46
-    vm: Vm,
47
-    env: Env,
44
+    vm: sen_core::Vm,
45
+    env: sen_core::Env,
48 46
 
49 47
     source_buffer: String,
50 48
     out_source_buffer: String,
51 49
     traits_buffer: String,
52 50
     genotype_buffer: String,
51
+
52
+    genotype_list: Option<Vec<sen_core::Genotype>>,
53
+
54
+    // temporary, these will all be removed eventually
55
+    trait_list: Option<sen_core::TraitList>,
53 56
 }
54 57
 
55 58
 #[wasm_bindgen]
@@ -57,13 +60,17 @@ impl Bridge {
57 60
     #[wasm_bindgen(constructor)]
58 61
     pub fn new() -> Bridge {
59 62
         Bridge {
60
-            vm: Vm::new(),
61
-            env: Env::new(),
63
+            vm: sen_core::Vm::new(),
64
+            env: sen_core::Env::new(),
62 65
 
63 66
             source_buffer: "source buffer".to_string(),
64 67
             out_source_buffer: "out_source buffer".to_string(),
65 68
             traits_buffer: "traits buffer".to_string(),
66 69
             genotype_buffer: "genotype buffer".to_string(),
70
+
71
+            genotype_list: None,
72
+
73
+            trait_list: None,
67 74
         }
68 75
     }
69 76
 
@@ -131,23 +138,52 @@ impl Bridge {
131 138
         self.vm.get_render_packet_geo_ptr(packet_number)
132 139
     }
133 140
 
134
-    pub fn build_traits(&self) -> i32 {
135
-        log("build_traits");
136
-        0
141
+    // todo: is bool the best return type?
142
+    pub fn build_traits(&mut self) -> bool {
143
+        if let Ok(trait_list) = sen_core::build_traits(&self.source_buffer) {
144
+            self.trait_list = Some(trait_list);
145
+            // todo: serialize trait_list
146
+            true
147
+        } else {
148
+            false
149
+        }
137 150
     }
138 151
 
139
-    pub fn single_genotype_from_seed(&self, _seed: i32) -> i32 {
140
-        log("single_genotype_from_seed");
141
-        0
152
+    pub fn single_genotype_from_seed(&mut self, seed: i32) -> bool {
153
+        // todo: deserialize trait_list from traits_buffer
154
+        // for the moment using self.trait_list THIS IS WRONG!!!
155
+        if let Some(ref trait_list) = self.trait_list {
156
+            if let Ok(genotype) = sen_core::Genotype::build_from_seed(trait_list, seed) {
157
+                self.genotype_list = Some(vec![genotype]);
158
+                return true
159
+            }
160
+        }
161
+        false
142 162
     }
143 163
 
144
-    pub fn create_initial_generation(&self, _population_size: i32, _seed: i32) -> i32 {
145
-        log("create_initial_generation");
146
-        0
164
+    // todo: is bool the best return type?
165
+    pub fn create_initial_generation(&mut self, population_size: i32, seed: i32) -> bool {
166
+        // todo: deserialize trait_list from traits_buffer
167
+        // for the moment using self.trait_list THIS IS WRONG!!!
168
+        if let Some(ref trait_list) = self.trait_list {
169
+            if let Ok(genotype_list) = sen_core::Genotype::build_genotypes(&trait_list, population_size, seed) {
170
+                self.genotype_list = Some(genotype_list);
171
+                return true
172
+            }
173
+        }
174
+
175
+        false
147 176
     }
148 177
 
149
-    pub fn genotype_move_to_buffer(&self, _index: i32) {
150
-        log("genotype_move_to_buffer");
178
+    pub fn genotype_move_to_buffer(&mut self, index: usize) -> bool {
179
+        if let Some(ref genotype_list) = self.genotype_list {
180
+            if let Some(ref _genotype) = genotype_list.get(index) {
181
+                // todo: serialize into genotype_buffer
182
+                unimplemented!();
183
+                // return true
184
+            }
185
+        }
186
+        false
151 187
     }
152 188
 
153 189
     pub fn script_cleanup(&self) {

+ 3
- 1
core/sen-core/src/compiler.rs View File

@@ -92,7 +92,9 @@ pub fn compile_program_for_trait(
92 92
     if let Some(useful_node) = clean_node(gen_initial_value) {
93 93
         initial_value_node = useful_node;
94 94
     } else {
95
-        return Err(Error::Compiler("cannot simplify gen_initial_value in compile_program_for_trait".to_string()));
95
+        return Err(Error::Compiler(
96
+            "cannot simplify gen_initial_value in compile_program_for_trait".to_string(),
97
+        ));
96 98
     }
97 99
 
98 100
     compiler.compile_common_prologue(&mut compilation, &ast)?;

+ 5
- 0
core/sen-core/src/error.rs View File

@@ -17,7 +17,9 @@ pub type Result<T> = ::std::result::Result<T, Error>;
17 17
 
18 18
 #[derive(Debug)]
19 19
 pub enum Error {
20
+    // these are lazy errors, used during dev as basically placeholder errors. remove them
20 21
     GeneralError,
22
+    NotedError(String),
21 23
 
22 24
     // colour
23 25
     //
@@ -51,4 +53,7 @@ pub enum Error {
51 53
 
52 54
     // geometry
53 55
     Geometry(String),
56
+
57
+    // gene
58
+    Gene(String),
54 59
 }

+ 211
- 0
core/sen-core/src/gene.rs View File

@@ -0,0 +1,211 @@
1
+// Copyright (C) 2019 Inderjit Gill
2
+
3
+// This program is free software: you can redistribute it and/or modify
4
+// it under the terms of the GNU General Public License as published by
5
+// the Free Software Foundation, either version 3 of the License, or
6
+// (at your option) any later version.
7
+
8
+// This program is distributed in the hope that it will be useful,
9
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+// GNU General Public License for more details.
12
+
13
+// You should have received a copy of the GNU General Public License
14
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
+
16
+use crate::colour::Colour;
17
+use crate::error::{Error, Result};
18
+use crate::keywords::Keyword;
19
+use crate::prng::PrngStateStruct;
20
+use crate::trait_list::{Trait, TraitList};
21
+use crate::vm::{Env, Var, Vm};
22
+
23
+/*
24
+GeneVar is a subset of the Var enum. Since Gene is a member of NodeMeta it
25
+needs the PartialEq trait and prng (which is used in the Var enum) uses
26
+XorShiftRng which doesn't implement PartialEq
27
+*/
28
+
29
+#[derive(Clone, Debug, PartialEq)]
30
+pub enum Gene {
31
+    Int(i32),
32
+    Float(f32),
33
+    Bool(bool),
34
+    Keyword(Keyword),
35
+    Long(u64),
36
+    Name(i32),
37
+    // Vector(Vec<Gene>),
38
+    Colour(Colour),
39
+    V2D(f32, f32),
40
+}
41
+
42
+impl Gene {
43
+    pub fn from_var(var: &Var) -> Result<Self> {
44
+        match var {
45
+            Var::Int(i) => Ok(Gene::Int(*i)),
46
+            Var::Float(fl) => Ok(Gene::Float(*fl)),
47
+            Var::Bool(b) => Ok(Gene::Bool(*b)),
48
+            Var::Keyword(kw) => Ok(Gene::Keyword(*kw)),
49
+            Var::Long(u) => Ok(Gene::Long(*u)),
50
+            Var::Name(i) => Ok(Gene::Name(*i)),
51
+            //Var::Vector() => Ok(Gene::Vector(_)),
52
+            Var::Colour(col) => Ok(Gene::Colour(*col)),
53
+            Var::V2D(fl1, fl2) => Ok(Gene::V2D(*fl1, *fl2)),
54
+            _ => Err(Error::Gene("from_var: incompatible input var".to_string())),
55
+        }
56
+    }
57
+
58
+    pub fn build_from_trait(vm: &mut Vm, t: &Trait) -> Result<Self> {
59
+        let env = Env::new();
60
+
61
+        vm.reset();
62
+
63
+        vm.building_with_trait_within_vector = t.within_vector;
64
+        vm.trait_within_vector_index = t.index;
65
+
66
+        vm.interpret(&env, &t.program)?;
67
+        let var = vm.top_stack_value()?;
68
+
69
+        vm.building_with_trait_within_vector = false;
70
+        vm.trait_within_vector_index = 0;
71
+
72
+        Gene::from_var(&var)
73
+    }
74
+}
75
+
76
+#[derive(Debug)]
77
+pub struct Genotype {
78
+    genes: Vec<Gene>,
79
+    current_gene_index: usize,
80
+}
81
+
82
+impl Genotype {
83
+    pub fn new() -> Self {
84
+        Genotype {
85
+            genes: Vec::new(),
86
+            current_gene_index: 0,
87
+        }
88
+    }
89
+
90
+    pub fn build_genotypes(
91
+        trait_list: &TraitList,
92
+        population_size: i32,
93
+        seed: i32,
94
+    ) -> Result<Vec<Self>> {
95
+        let mut genotypes: Vec<Genotype> = Vec::new();
96
+        let mut prng = PrngStateStruct::new(seed, 1.0, 655536.0);
97
+
98
+        for _ in 0..population_size {
99
+            let genotype_seed = prng.prng_f32_defined_range() as i32;
100
+            genotypes.push(Genotype::build_from_seed(trait_list, genotype_seed)?);
101
+        }
102
+
103
+        Ok(genotypes)
104
+    }
105
+
106
+    // build_from_trait_list
107
+    pub fn build_from_seed(trait_list: &TraitList, seed: i32) -> Result<Self> {
108
+        let mut vm = Vm::new();
109
+        let mut genotype = Genotype::new();
110
+
111
+        // the seed is set once per genotype (should it be once per-gene?)
112
+        //
113
+        vm.prng_state.set_state(seed);
114
+
115
+        for t in &trait_list.traits {
116
+            genotype.genes.push(Gene::build_from_trait(&mut vm, t)?);
117
+        }
118
+
119
+        Ok(genotype)
120
+    }
121
+
122
+    pub fn build_from_initial_values(trait_list: &TraitList) -> Result<Self> {
123
+        let mut genotype = Genotype::new();
124
+
125
+        for t in &trait_list.traits {
126
+            genotype.genes.push(Gene::from_var(&t.initial_value)?);
127
+        }
128
+
129
+        Ok(genotype)
130
+    }
131
+
132
+    // crossover
133
+}
134
+
135
+#[cfg(test)]
136
+mod tests {
137
+    use super::*;
138
+    use crate::parser::parse;
139
+
140
+    fn compile_trait_list(s: &str) -> Result<TraitList> {
141
+        let (ast, _) = parse(s).unwrap();
142
+        TraitList::compile(&ast)
143
+    }
144
+
145
+    fn gene_float(g: &Gene, expected: f32) {
146
+        if let Gene::Float(f) = g {
147
+            assert_eq!(*f, expected);
148
+        } else {
149
+            assert!(false);
150
+        }
151
+    }
152
+
153
+    fn gene_2d(g: &Gene, expected_x: f32, expected_y: f32) {
154
+        if let Gene::V2D(x, y) = g {
155
+            assert_eq!(*x, expected_x);
156
+            assert_eq!(*y, expected_y);
157
+        } else {
158
+            assert!(false);
159
+        }
160
+    }
161
+
162
+    #[test]
163
+    fn genotype_from_initial_values_1() {
164
+        let trait_list =
165
+            compile_trait_list("(+ {4 (gen/scalar min: 2 max: 9)}) {6 (gen/scalar min: 2 max: 9)}")
166
+                .unwrap();
167
+
168
+        let genotype = Genotype::build_from_initial_values(&trait_list).unwrap();
169
+
170
+        assert_eq!(genotype.genes.len(), 2);
171
+        gene_float(&genotype.genes[0], 4.0);
172
+        gene_float(&genotype.genes[1], 6.0);
173
+    }
174
+
175
+    #[test]
176
+    fn genotype_from_initial_values_2() {
177
+        let trait_list =
178
+            compile_trait_list("{[[0.1 0.2] [0.3 0.4]] (gen/2d min: 50 max: 60)}").unwrap();
179
+
180
+        let genotype = Genotype::build_from_initial_values(&trait_list).unwrap();
181
+
182
+        assert_eq!(genotype.genes.len(), 2);
183
+        gene_2d(&genotype.genes[0], 0.1, 0.2);
184
+        gene_2d(&genotype.genes[1], 0.3, 0.4);
185
+    }
186
+
187
+    #[test]
188
+    fn genotype_from_seed_1() {
189
+        let trait_list =
190
+            compile_trait_list("(+ {4 (gen/scalar min: 2 max: 9)}) {6 (gen/scalar min: 2 max: 9)}")
191
+                .unwrap();
192
+
193
+        let genotype = Genotype::build_from_seed(&trait_list, 432).unwrap();
194
+
195
+        assert_eq!(genotype.genes.len(), 2);
196
+        gene_float(&genotype.genes[0], 8.82988);
197
+        gene_float(&genotype.genes[1], 6.2474613);
198
+    }
199
+
200
+    #[test]
201
+    fn genotype_from_seed_2() {
202
+        let trait_list =
203
+            compile_trait_list("{[[0.1 0.2] [0.3 0.4]] (gen/2d min: 50 max: 60)}").unwrap();
204
+
205
+        let genotype = Genotype::build_from_seed(&trait_list, 432).unwrap();
206
+
207
+        assert_eq!(genotype.genes.len(), 2);
208
+        gene_2d(&genotype.genes[0], 59.75697, 56.067802);
209
+        gene_2d(&genotype.genes[1], 55.85068, 57.474014);
210
+    }
211
+}

+ 13
- 1
core/sen-core/src/lib.rs View File

@@ -27,7 +27,7 @@
27 27
 mod colour;
28 28
 mod ease;
29 29
 mod focal;
30
-mod genetic;
30
+mod gene;
31 31
 mod interp;
32 32
 mod keywords;
33 33
 mod lexer;
@@ -38,6 +38,7 @@ mod opcodes;
38 38
 mod path;
39 39
 mod prng;
40 40
 mod repeat;
41
+mod trait_list;
41 42
 mod uvmapper;
42 43
 
43 44
 pub mod compiler;
@@ -51,6 +52,9 @@ use crate::parser::*;
51 52
 use crate::vm::*;
52 53
 
53 54
 pub use crate::compiler::*;
55
+pub use crate::gene::Genotype;
56
+pub use crate::trait_list::TraitList;
57
+pub use crate::vm::{Env, Vm};
54 58
 
55 59
 pub fn run_program_with_preamble(vm: &mut Vm, program: &Program) -> Result<Var> {
56 60
     let env = Env::new();
@@ -77,6 +81,14 @@ pub fn compile_to_render_packets(vm: &mut Vm, s: &str) -> Result<i32> {
77 81
     Ok(vm.geometry.get_num_render_packets() as i32)
78 82
 }
79 83
 
84
+pub fn build_traits(s: &str) -> Result<TraitList> {
85
+    let (ast, _) = parse(s)?;
86
+
87
+    let trait_list = TraitList::compile(&ast)?;
88
+
89
+    Ok(trait_list)
90
+}
91
+
80 92
 pub fn compile_and_execute(s: &str) -> Result<Var> {
81 93
     let mut vm = Vm::new();
82 94
     // todo: cache the preamble program

+ 181
- 13
core/sen-core/src/native.rs View File

@@ -400,13 +400,13 @@ pub fn build_native_fn_hash() -> HashMap<Native, NativeCallback> {
400 400
     h.insert(Native::GenStrayInt, gen_stray_int);
401 401
     h.insert(Native::GenStray, gen_stray);
402 402
     h.insert(Native::GenStray2D, gen_stray_2d);
403
-    // BIND("gen/stray-3d", gen_stray_3d);
404
-    // BIND("gen/stray-4d", gen_stray_4d);
403
+    h.insert(Native::GenStray3D, gen_stray_3d);
404
+    h.insert(Native::GenStray4D, gen_stray_4d);
405 405
     h.insert(Native::GenInt, gen_int);
406 406
     h.insert(Native::GenScalar, gen_scalar);
407 407
     h.insert(Native::Gen2D, gen_2d);
408
-    // BIND("gen/select", gen_select); // broken?
409
-    // BIND("gen/col", gen_col);
408
+    h.insert(Native::GenSelect, gen_select); // not implemented
409
+    h.insert(Native::GenCol, gen_col);
410 410
 
411 411
     h
412 412
 }
@@ -2159,7 +2159,7 @@ pub fn prng_values(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<V
2159 2159
 
2160 2160
     if let Some(ref mut prng_state) = ref_mut_prng_state {
2161 2161
         for _ in 0..(num.unwrap() as i32) {
2162
-            let f = prng_state.prng_f32();
2162
+            let f = prng_state.prng_f32_defined_range();
2163 2163
             vs.push(Var::Float(f))
2164 2164
         }
2165 2165
     }
@@ -2182,7 +2182,7 @@ pub fn prng_value(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Va
2182 2182
     }
2183 2183
 
2184 2184
     if let Some(ref mut prng_state) = ref_mut_prng_state {
2185
-        let f = prng_state.prng_f32();
2185
+        let f = prng_state.prng_f32_defined_range();
2186 2186
         return Ok(Var::Float(f));
2187 2187
     }
2188 2188
 
@@ -2861,7 +2861,7 @@ pub fn focal_value(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<V
2861 2861
 //
2862 2862
 pub fn gen_stray_int(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
2863 2863
     let mut from: Option<f32> = Some(1.0);
2864
-    let mut by : Option<f32> = Some(0.2);
2864
+    let mut by: Option<f32> = Some(0.2);
2865 2865
 
2866 2866
     let mut args_pointer = vm.sp - (num_args * 2);
2867 2867
     for _ in 0..num_args {
@@ -2885,7 +2885,7 @@ pub fn gen_stray_int(vm: &mut Vm, _program: &Program, num_args: usize) -> Result
2885 2885
 
2886 2886
 pub fn gen_stray(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
2887 2887
     let mut from: Option<f32> = Some(1.0);
2888
-    let mut by : Option<f32> = Some(0.2);
2888
+    let mut by: Option<f32> = Some(0.2);
2889 2889
 
2890 2890
     let mut args_pointer = vm.sp - (num_args * 2);
2891 2891
     for _ in 0..num_args {
@@ -2910,11 +2910,14 @@ pub fn gen_stray(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var
2910 2910
 
2911 2911
 pub fn gen_stray_2d(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
2912 2912
     if !vm.building_with_trait_within_vector {
2913
-        return Err(Error::Bind("gen_stray_2d should always be called with vm.building_with_trait_within_vector".to_string()))
2913
+        return Err(Error::Bind(
2914
+            "gen_stray_2d should always be called with vm.building_with_trait_within_vector"
2915
+                .to_string(),
2916
+        ));
2914 2917
     }
2915 2918
 
2916 2919
     let mut from: Option<(f32, f32)> = Some((10.0, 10.0));
2917
-    let mut by : Option<(f32, f32)> = Some((1.0, 1.0));
2920
+    let mut by: Option<(f32, f32)> = Some((1.0, 1.0));
2918 2921
 
2919 2922
     let mut args_pointer = vm.sp - (num_args * 2);
2920 2923
     for _ in 0..num_args {
@@ -2941,11 +2944,121 @@ pub fn gen_stray_2d(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<
2941 2944
         by_index = mathutil::absf(by.1);
2942 2945
         from_index = from.1;
2943 2946
     } else {
2944
-        return Err(Error::Bind("gen_stray_2d invalid trait_within_vector_index value".to_string()));
2947
+        return Err(Error::Bind(
2948
+            "gen_stray_2d invalid trait_within_vector_index value".to_string(),
2949
+        ));
2945 2950
     }
2946 2951
 
2947 2952
     // pick a scalar between min and max
2948
-    let value = vm.prng_state.prng_f32_range(from_index - by_index, from_index + by_index);
2953
+    let value = vm
2954
+        .prng_state
2955
+        .prng_f32_range(from_index - by_index, from_index + by_index);
2956
+
2957
+    Ok(Var::Float(value))
2958
+}
2959
+
2960
+pub fn gen_stray_3d(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
2961
+    if !vm.building_with_trait_within_vector {
2962
+        return Err(Error::Bind(
2963
+            "gen_stray_3d should always be called with vm.building_with_trait_within_vector"
2964
+                .to_string(),
2965
+        ));
2966
+    }
2967
+
2968
+    let mut from: Option<&Vec<Var>> = None;
2969
+    let mut by: Option<&Vec<Var>> = None;
2970
+
2971
+    let mut args_pointer = vm.sp - (num_args * 2);
2972
+    for _ in 0..num_args {
2973
+        let label = &vm.stack[args_pointer];
2974
+        let value = &vm.stack[args_pointer + 1];
2975
+        args_pointer += 2;
2976
+
2977
+        if let Var::Int(iname) = label {
2978
+            read_vector!(from, Keyword::From, iname, value);
2979
+            read_vector!(by, Keyword::By, iname, value);
2980
+        }
2981
+    }
2982
+
2983
+    if from.is_none() || by.is_none() {
2984
+        return Err(Error::Bind(
2985
+            "gen_stray_3d requires both from and by parameters".to_string(),
2986
+        ));
2987
+    }
2988
+
2989
+    let index = vm.trait_within_vector_index;
2990
+
2991
+    let from = if let Some(var) = from.unwrap().get(index) {
2992
+        Var::get_float_value(&var)?
2993
+    } else {
2994
+        return Err(Error::Bind(
2995
+            "gen_stray_3d requires both from and by parameters".to_string(),
2996
+        ));
2997
+    };
2998
+
2999
+    let by = if let Some(var) = by.unwrap().get(index) {
3000
+        Var::get_float_value(&var)?
3001
+    } else {
3002
+        return Err(Error::Bind(
3003
+            "gen_stray_3d requires both from and by parameters".to_string(),
3004
+        ));
3005
+    };
3006
+
3007
+    // pick a scalar between min and max
3008
+    let value = vm.prng_state.prng_f32_range(from - by, from + by);
3009
+
3010
+    Ok(Var::Float(value))
3011
+}
3012
+
3013
+pub fn gen_stray_4d(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
3014
+    if !vm.building_with_trait_within_vector {
3015
+        return Err(Error::Bind(
3016
+            "gen_stray_4d should always be called with vm.building_with_trait_within_vector"
3017
+                .to_string(),
3018
+        ));
3019
+    }
3020
+
3021
+    let mut from: Option<&Vec<Var>> = None;
3022
+    let mut by: Option<&Vec<Var>> = None;
3023
+
3024
+    let mut args_pointer = vm.sp - (num_args * 2);
3025
+    for _ in 0..num_args {
3026
+        let label = &vm.stack[args_pointer];
3027
+        let value = &vm.stack[args_pointer + 1];
3028
+        args_pointer += 2;
3029
+
3030
+        if let Var::Int(iname) = label {
3031
+            read_vector!(from, Keyword::From, iname, value);
3032
+            read_vector!(by, Keyword::By, iname, value);
3033
+        }
3034
+    }
3035
+
3036
+    if from.is_none() || by.is_none() {
3037
+        return Err(Error::Bind(
3038
+            "gen_stray_4d requires both from and by parameters".to_string(),
3039
+        ));
3040
+    }
3041
+
3042
+    let index = vm.trait_within_vector_index;
3043
+
3044
+    let from = if let Some(var) = from.unwrap().get(index) {
3045
+        Var::get_float_value(&var)?
3046
+    } else {
3047
+        return Err(Error::Bind(
3048
+            "gen_stray_4d requires both from and by parameters".to_string(),
3049
+        ));
3050
+    };
3051
+
3052
+    let by = if let Some(var) = by.unwrap().get(index) {
3053
+        Var::get_float_value(&var)?
3054
+    } else {
3055
+        return Err(Error::Bind(
3056
+            "gen_stray_4d requires both from and by parameters".to_string(),
3057
+        ));
3058
+    };
3059
+
3060
+    // pick a scalar between min and max
3061
+    let value = vm.prng_state.prng_f32_range(from - by, from + by);
2949 3062
 
2950 3063
     Ok(Var::Float(value))
2951 3064
 }
@@ -2967,7 +3080,9 @@ pub fn gen_int(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var>
2967 3080
     }
2968 3081
 
2969 3082
     // pick a scalar between min and max
2970
-    let value = vm.prng_state.prng_f32_range(min.unwrap(), max.unwrap() + 1.0);
3083
+    let value = vm
3084
+        .prng_state
3085
+        .prng_f32_range(min.unwrap(), max.unwrap() + 1.0);
2971 3086
 
2972 3087
     // todo: c-version returned f32, is it ok to cast this to i32?
2973 3088
     Ok(Var::Float(value.floor()))
@@ -3017,6 +3132,59 @@ pub fn gen_2d(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
3017 3132
     Ok(Var::V2D(x, y))
3018 3133
 }
3019 3134
 
3135
+pub fn gen_select(_vm: &mut Vm, _program: &Program, _num_args: usize) -> Result<Var> {
3136
+    // 'from' parameter should be a list
3137
+    // i.e. (gen/select from: '(1 2 3 4 5))
3138
+    //
3139
+    // this prevents any confusion between a vector and vec_2d
3140
+    // e.g. (gen/select from: [1 2 3 4 5]) vs. (gen/select from: [1 2])
3141
+
3142
+    // let mut from: Option<&Var> = None;
3143
+
3144
+    // let mut args_pointer = vm.sp - (num_args * 2);
3145
+    // for _ in 0..num_args {
3146
+    //     let label = &vm.stack[args_pointer];
3147
+    //     let value = &vm.stack[args_pointer + 1];
3148
+    //     args_pointer += 2;
3149
+
3150
+    //     if let Var::Int(iname) = label {
3151
+    //         // read_???!(from, Keyword::From, iname, value);
3152
+    //     }
3153
+    // }
3154
+
3155
+    unimplemented!();
3156
+}
3157
+
3158
+pub fn gen_col(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
3159
+    let mut alpha: Option<f32> = None;
3160
+
3161
+    let mut args_pointer = vm.sp - (num_args * 2);
3162
+    for _ in 0..num_args {
3163
+        let label = &vm.stack[args_pointer];
3164
+        let value = &vm.stack[args_pointer + 1];
3165
+        args_pointer += 2;
3166
+
3167
+        if let Var::Int(iname) = label {
3168
+            read_float!(alpha, Keyword::Alpha, iname, value);
3169
+        }
3170
+    }
3171
+
3172
+    let alpha = if let Some(alpha) = alpha {
3173
+        alpha
3174
+    } else {
3175
+        // no alpha was given so generate a random value
3176
+        vm.prng_state.prng_f32_range(0.0, 1.0)
3177
+    };
3178
+
3179
+    Ok(Var::Colour(Colour::new(
3180
+        ColourFormat::Rgb,
3181
+        vm.prng_state.prng_f32_range(0.0, 1.0),
3182
+        vm.prng_state.prng_f32_range(0.0, 1.0),
3183
+        vm.prng_state.prng_f32_range(0.0, 1.0),
3184
+        alpha,
3185
+    )))
3186
+}
3187
+
3020 3188
 #[cfg(test)]
3021 3189
 mod tests {
3022 3190
     use crate::colour::ColourFormat;

+ 1
- 1
core/sen-core/src/parser.rs View File

@@ -17,7 +17,7 @@ use std::collections::HashMap;
17 17
 use std::str::FromStr;
18 18
 
19 19
 use crate::error::{Error, Result};
20
-use crate::genetic::Gene;
20
+use crate::gene::Gene;
21 21
 use crate::keywords::Keyword;
22 22
 use crate::lexer::{tokenize, Token};
23 23
 use crate::native::Native;

+ 49
- 23
core/sen-core/src/prng.rs View File

@@ -82,35 +82,16 @@ fn as_u8(i: i32) -> u8 {
82 82
 
83 83
 impl PrngStateStruct {
84 84
     pub fn new(seed: i32, min: f32, max: f32) -> Self {
85
-        let seedy: [u8; 16] = [
86
-            as_u8(seed),
87
-            as_u8(seed + 1),
88
-            as_u8(seed + seed - 2),
89
-            as_u8(seed + 3),
90
-            as_u8(seed + seed - 4),
91
-            as_u8(seed + 5),
92
-            as_u8(seed + seed - 6),
93
-            as_u8(seed + 7),
94
-            as_u8(seed + seed - 8),
95
-            as_u8(seed + 9),
96
-            as_u8(seed + seed - 10),
97
-            as_u8(seed + 11),
98
-            as_u8(seed + seed - 12),
99
-            as_u8(seed + 13),
100
-            as_u8(seed + seed - 14),
101
-            as_u8(seed + 15),
102
-        ];
103
-
104 85
         PrngStateStruct {
105
-            rng: XorShiftRng::from_seed(seedy),
86
+            rng: PrngStateStruct::make_xor_shift_rng(seed),
106 87
             min,
107 88
             max,
108 89
         }
109 90
     }
110 91
 
111
-    // pub fn prng_set_state(&mut self, seed: [u8; 16]) {
112
-    //     self.rnd_pcg_seed(seed)
113
-    // }
92
+    pub fn set_state(&mut self, seed: i32) {
93
+        self.rng = PrngStateStruct::make_xor_shift_rng(seed);
94
+    }
114 95
 
115 96
     // pub fn prng_i32_range(&mut self, min: i32, max: i32) -> i32 {
116 97
     //     self.rnd_pcg_range(min, max)
@@ -128,6 +109,11 @@ impl PrngStateStruct {
128 109
         (value * (max - min)) + min
129 110
     }
130 111
 
112
+    pub fn prng_f32_defined_range(&mut self) -> f32 {
113
+        let value = self.prng_f32();
114
+        (value * (self.max - self.min)) + self.min
115
+    }
116
+
131 117
     pub fn prng_f32_around(&mut self, val: f32, percent: f32, min: f32, max: f32) -> f32 {
132 118
         let value = self.prng_f32();
133 119
         let range = ((max - min) / 100.0) * percent;
@@ -137,6 +123,29 @@ impl PrngStateStruct {
137 123
 
138 124
         clamp(res, min, max)
139 125
     }
126
+
127
+    fn make_xor_shift_rng(seed: i32) -> XorShiftRng {
128
+        let seedy: [u8; 16] = [
129
+            as_u8(seed),
130
+            as_u8(seed + 1),
131
+            as_u8(seed + seed - 2),
132
+            as_u8(seed + 3),
133
+            as_u8(seed + seed - 4),
134
+            as_u8(seed + 5),
135
+            as_u8(seed + seed - 6),
136
+            as_u8(seed + 7),
137
+            as_u8(seed + seed - 8),
138
+            as_u8(seed + 9),
139
+            as_u8(seed + seed - 10),
140
+            as_u8(seed + 11),
141
+            as_u8(seed + seed - 12),
142
+            as_u8(seed + 13),
143
+            as_u8(seed + seed - 14),
144
+            as_u8(seed + 15),
145
+        ];
146
+
147
+        XorShiftRng::from_seed(seedy)
148
+    }
140 149
 }
141 150
 
142 151
 fn fade(t: f32) -> f32 {
@@ -230,6 +239,23 @@ pub mod tests {
230 239
     }
231 240
 
232 241
     #[test]
242
+    pub fn test_prng_value2() {
243
+        is_debug_str(
244
+            "(define p (prng/build seed: 5938 min: 3 max: 9))
245
+             (probe scalar: (prng/value from: p))
246
+             (probe scalar: (prng/value from: p))
247
+             (probe scalar: (prng/value from: p))
248
+             (probe scalar: (prng/value from: p))
249
+             (probe scalar: (prng/value from: p))
250
+             (probe scalar: (prng/value from: p))
251
+             (probe scalar: (prng/value from: p))
252
+             (probe scalar: (prng/value from: p))
253
+             (probe scalar: (prng/value from: p))",
254
+            "5.3797703 7.0697656 4.541839 7.1620464 6.7335386 3.5603561 3.4189374 3.1284251 8.890152",
255
+        );
256
+    }
257
+
258
+    #[test]
233 259
     pub fn test_prng_values() {
234 260
         is_debug_str(
235 261
             "(define p (prng/build seed: 5 min: 0 max: 1))

core/sen-core/src/genetic.rs → core/sen-core/src/trait_list.rs View File

@@ -13,10 +13,8 @@
13 13
 // You should have received a copy of the GNU General Public License
14 14
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
15 15
 
16
-use crate::colour::Colour;
17 16
 use crate::compiler::{compile_program_1, compile_program_for_trait, Program};
18 17
 use crate::error::Result;
19
-use crate::keywords::Keyword;
20 18
 use crate::parser::{Node, NodeMeta};
21 19
 use crate::run_program_with_preamble;
22 20
 use crate::vm::{Var, Vm};
@@ -26,13 +24,13 @@ pub struct Trait {
26 24
     // todo: replace within_vector and index with a single Option<usize>
27 25
 
28 26
     // true == instantiated as one of multiple traits within a vector
29
-    within_vector: bool,
27
+    pub within_vector: bool,
30 28
 
31 29
     // if within_vector then this is the index within the parent vector
32
-    index: usize,
30
+    pub index: usize,
33 31
 
34
-    initial_value: Var,
35
-    program: Program,
32
+    pub initial_value: Var,
33
+    pub program: Program,
36 34
 }
37 35
 
38 36
 impl Trait {
@@ -87,19 +85,20 @@ impl Trait {
87 85
 
88 86
 #[derive(Debug)]
89 87
 pub struct TraitList {
90
-    traits: Vec<Trait>,
91
-    seed_value: i32,
88
+    pub traits: Vec<Trait>,
89
+    pub seed_value: i32,
92 90
 }
93 91
 
94 92
 impl TraitList {
95 93
     fn new() -> Self {
96 94
         TraitList {
97 95
             traits: Vec::new(),
96
+            // todo: when is the seed_value set properly?
98 97
             seed_value: 42,
99 98
         }
100 99
     }
101 100
 
102
-    fn compile(ast: &[Node]) -> Result<Self> {
101
+    pub fn compile(ast: &[Node]) -> Result<Self> {
103 102
         let mut trait_list = TraitList::new();
104 103
 
105 104
         for n in ast {
@@ -170,7 +169,7 @@ impl TraitList {
170 169
             match n {
171 170
                 Node::Whitespace(_, _) | Node::Comment(_, _) => {
172 171
                     // ignoring whitespace and comments
173
-                },
172
+                }
174 173
                 _ => {
175 174
                     let t = Trait::compile(n, &meta.parameter_ast, Some(i))?;
176 175
                     self.traits.push(t);
@@ -183,45 +182,6 @@ impl TraitList {
183 182
     }
184 183
 }
185 184
 
186
-/*
187
-GeneVar is a subset of the Var enum. Since Gene is a member of NodeMeta it
188
-needs the PartialEq trait and prng (which is used in the Var enum) uses
189
-XorShiftRng which doesn't implement PartialEq
190
-*/
191
-// todo: conversion between GeneVar and Var
192
-
193
-#[derive(Clone, Debug, PartialEq)]
194
-pub enum GeneVar {
195
-    Int(i32),
196
-    Float(f32),
197
-    Bool(bool),
198
-    Keyword(Keyword),
199
-    Long(u64),
200
-    Name(i32),
201
-    Vector(Vec<GeneVar>),
202
-    Colour(Colour),
203
-    V2D(f32, f32),
204
-}
205
-
206
-#[derive(Debug, PartialEq)]
207
-pub struct Gene {
208
-    base: GeneVar,
209
-}
210
-
211
-#[derive(Debug)]
212
-pub struct Genotype {
213
-    genes: Vec<Gene>,
214
-
215
-    // set/get by compiler when compiling program with a genotype
216
-    // todo: ????
217
-    current_gene: Gene, // how is this going to work?
218
-}
219
-
220
-#[derive(Debug)]
221
-pub struct GenotypeList {
222
-    genotypes: Vec<Genotype>,
223
-}
224
-
225 185
 #[cfg(test)]
226 186
 mod tests {
227 187
     use super::*;
@@ -280,7 +240,7 @@ mod tests {
280 240
                 assert_eq!(trait_list.traits.len(), 2);
281 241
                 trait_multiple_v2d(&trait_list.traits[0], 0.1, 0.2, 0);
282 242
                 trait_multiple_v2d(&trait_list.traits[1], 0.3, 0.4, 1);
283
-            },
243
+            }
284 244
             Err(_) => assert!(false),
285 245
         };
286 246
     }

+ 9
- 0
core/sen-core/src/vm.rs View File

@@ -82,6 +82,15 @@ impl fmt::Display for Var {
82 82
     }
83 83
 }
84 84
 
85
+impl Var {
86
+    pub fn get_float_value(var: &Var) -> Result<f32> {
87
+        match var {
88
+            Var::Float(f) => Ok(*f),
89
+            _ => Err(Error::NotedError("expected a Var::Float".to_string())),
90
+        }
91
+    }
92
+}
93
+
85 94
 // todo: what is the point of Env?
86 95
 pub struct Env {
87 96
     function_ptr: i32,

Loading…
Cancel
Save