mirror of
				https://github.com/Dummi26/mers.git
				synced 2025-10-31 11:46:15 +01:00 
			
		
		
		
	fixed examples, fixed bug due to VType changes
This commit is contained in:
		
							parent
							
								
									d94f727eaa
								
							
						
					
					
						commit
						3032d3c115
					
				| @ -9,7 +9,7 @@ fn random(min int max int) { | ||||
| } | ||||
| fn rnd() { | ||||
|     r := random(5 15) | ||||
|     switch r { | ||||
|     switch! r { | ||||
|         int r r | ||||
|         [] [] 10 | ||||
|     } | ||||
|  | ||||
| @ -1,51 +0,0 @@ | ||||
| lib mers_libs/gui | ||||
| 
 | ||||
| base = gui_init() | ||||
| column = base.gui_add(Column: []) | ||||
| 
 | ||||
| text = column.gui_add(Text: "Welcome to MERS GUI!") | ||||
| 
 | ||||
| button = column.gui_add(Button: "This is a button.") | ||||
| second_button = column.gui_add(Button: "This is a second button.") | ||||
| 
 | ||||
| text_state = -2 | ||||
| second_text = column.gui_add(Text: "press the button above to remove this text!") | ||||
| 
 | ||||
| loop { | ||||
|     for event gui_updates() { | ||||
|         switch! event { | ||||
|             ButtonPressed([int ...]) { | ||||
|                 e = event.noenum() | ||||
|                 match e { | ||||
|                     &e.eq(&button) println("First button pressed") | ||||
|                     &e.eq(&second_button) { | ||||
|                         // don't match on text_state because we need to change the original from inside the match statement | ||||
|                         state = text_state | ||||
|                         match state { | ||||
|                             // the first, third, fifth, ... time the button is pressed: remove the text | ||||
|                             text_state.mod(2).eq(0) { | ||||
|                                 if text_state.eq(-2) { | ||||
|                                     // the first time the button is pressed | ||||
|                                     text_state = 0 | ||||
|                                     set_title("keep pressing the button!") | ||||
|                                 } | ||||
|                                 second_text.gui_remove() | ||||
|                             } | ||||
|                             // the 2nd, 4th, 6th, ... time the button is pressed: add the text back | ||||
|                             text_state.eq(1) second_text = column.gui_add(Text: "i'm back!") | ||||
|                             text_state.eq(3) second_text = column.gui_add(Text: "you can't fully get rid of me!") | ||||
|                             true { | ||||
|                                 second_text = column.gui_add(Text: "i always come back") | ||||
|                                 // restart (set text_state to 0) | ||||
|                                 text_state = -1 | ||||
|                             } | ||||
|                         } | ||||
|                         text_state = text_state.add(1) | ||||
|                     } | ||||
|                     true println("A different button was pressed (unreachable)") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     [] | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| lib mers_libs/http_requests | ||||
| 
 | ||||
| t = thread(() { | ||||
|     // because this downloads for so long, the println() will appear after the other one. | ||||
|     http_get("https:\//raw.githubusercontent.com/dwyl/english-words/master/words.txt").assume_no_enum() | ||||
|     println("got words from word list!") | ||||
| }) | ||||
| 
 | ||||
| sleep(0.1) | ||||
| 
 | ||||
| // this will finish before the thread does. | ||||
| http_get("https:\//github.com/").assume_no_enum() | ||||
| println("got github start page as html") | ||||
| 
 | ||||
| t.await() | ||||
| 
 | ||||
| http_get("not a url").debug() | ||||
| @ -1,4 +1,4 @@ | ||||
| fn map_string_to_int(list [string ...] func fn((string int))) { | ||||
| fn map_string_to_int(list [string ...], func fn((string) int)) { | ||||
|     // return a function that can be used as an iterator | ||||
|     () { | ||||
|         // this function will be called by the for loop | ||||
| @ -36,4 +36,4 @@ fn square_numbers() { | ||||
| for n square_numbers() { | ||||
|     println(n.to_string()) | ||||
|     n >= 100 | ||||
| } | ||||
| } | ||||
| @ -1,74 +0,0 @@ | ||||
| lib mers_libs/gui | ||||
| 
 | ||||
| // GUI for xrandr, because arandr doesn't let me change the framerates. | ||||
| // [ WIP ] | ||||
| 
 | ||||
| base = gui_init() | ||||
| 
 | ||||
| set_title("MersRandr") | ||||
| 
 | ||||
| randr_output = run_command("xrandr") | ||||
| 
 | ||||
| switch! randr_output { | ||||
|     Err(string) { | ||||
|         println(randr_output.noenum()) | ||||
|     } | ||||
|     [[]/int string string] { | ||||
|         lines = randr_output.1.regex(".*") | ||||
|         screen_name = "" | ||||
|         screen_resolutions = [["" ["" ...]] ...] | ||||
|         screens = [ | ||||
|             [ | ||||
|                 screen_name | ||||
|                 screen_resolutions | ||||
|             ] | ||||
|         ...] | ||||
|         &screen_resolutions.pop() | ||||
|         &screens.pop() | ||||
|         for line lines { | ||||
|             if line.starts_with("Screen ") { | ||||
|                 // ignore | ||||
|             } else if line.starts_with("   ") { | ||||
|                 // split at spaces (and ignore +*) | ||||
|                 refresh_rates = line.regex("[^ +\\*]+").assume_no_enum() | ||||
|                 resolution = &refresh_rates.remove(0).assume1() | ||||
|                 print("{0} ::".format(resolution)) | ||||
|                 for rate refresh_rates { | ||||
|                     print(" \"{0}\"".format(rate)) | ||||
|                 } | ||||
|                 &screen_resolutions.push([resolution refresh_rates]) | ||||
|                 println("") | ||||
|             } else { | ||||
|                 index = line.index_of(" ") | ||||
|                 switch! index { | ||||
|                     int { | ||||
|                         if not(screen_name.len().eq(0)) { | ||||
|                             &screens.push([screen_name screen_resolutions]) | ||||
|                         } | ||||
|                         screen_resolutions = [ ...] | ||||
|                         screen_name = line.substring(0 index) | ||||
|                         println("> \"{0}\"".format(screen_name)) | ||||
|                     } | ||||
|                     [] {} | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if not(screen_name.len().eq(0)) { | ||||
|             &screens.push([screen_name screen_resolutions]) | ||||
|         } | ||||
|         for screen screens { | ||||
|             println(screen.0) | ||||
|             gui_screen = base.gui_add(Row: []) | ||||
|             gui_name = gui_screen.gui_add(Text: screen.0) | ||||
|             for res screen.1 { | ||||
|                 gui_resolution = gui_screen.gui_add(Button: res.0) | ||||
|                 print("  ") | ||||
|                 println(res.0) | ||||
|                 for rate res.1 { | ||||
|                     print("    ") | ||||
|                     println(rate) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,205 +0,0 @@ | ||||
| lib mers_libs/http_requests | ||||
| lib mers_libs/gui | ||||
| 
 | ||||
| // MusicDB is a private project of mine. | ||||
| // Basically, a SBC is hooked up to some speakers. | ||||
| // It has a database of my songs and can play them. | ||||
| // It can be controlled through HTTP requests, such as | ||||
| //   p- to stop | ||||
| //   p+ to play | ||||
| //   qi to get the queue index / playback position | ||||
| //   l to list all the songs | ||||
| //   ql or qL to list the queue | ||||
| //   ... | ||||
| // this mers program should work as a very simple gui to remotely control | ||||
| // the playback of songs. It should be able to add/remove songs to/from the queue, | ||||
| // to start/stop playback, and to display some information about the current song. | ||||
| 
 | ||||
| // the url used to connect to the SBC and use the HTTP api | ||||
| api_url = "http:\//192.168.2.103:26315/api/raw?" | ||||
| 
 | ||||
| // start the GUI | ||||
| base = gui_init() | ||||
| set_title("Mers MusicDB Remote") | ||||
| 
 | ||||
| playback_controls = base.gui_add(Row: []) | ||||
| play_button = playback_controls.gui_add(Button: "Play") | ||||
| stop_button = playback_controls.gui_add(Button: "Stop") | ||||
| 
 | ||||
| // these functions abstract away the api interactions | ||||
| // because they aren't pretty. | ||||
| // feel free to skip past this section and look at the gui code instead | ||||
| fn make_api_request(to_api string) { | ||||
|     http_get(api_url.add(to_api)) | ||||
| } | ||||
| fn get_queue_index() { | ||||
|     r = make_api_request("qi") | ||||
|     switch! r { | ||||
|         string { | ||||
|             r.regex("[0-9]").assume_no_enum().get(0).assume1().parse_int().assume1() | ||||
|         } | ||||
|         // return the error | ||||
|         Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r | ||||
|     } | ||||
| } | ||||
| fn get_db_contents() { | ||||
|     // list only 7 = 1 (title) + 2 (artist) + 4 (album) | ||||
|     r = make_api_request("lo7,") | ||||
|     switch! r { | ||||
|         string { | ||||
|             entries = r.regex("#.*:\n.*\n.*\n.*").assume_no_enum() | ||||
|             // initialize the list with a default value | ||||
|             // because mers doesnt know the inner type without it. | ||||
|             db = [[0 "title" "artist" "album"] ...] | ||||
|             &db.remove(0) | ||||
|             for entry entries { | ||||
|                 lines = entry.regex(".*") | ||||
|                 switch! lines { | ||||
|                     [string ...] { | ||||
|                         index_line = &lines.get(0).assume1() | ||||
|                         index = index_line.substring(1 index_line.len().sub(1)).parse_int().assume1() | ||||
|                         title = &lines.get(1).assume1().substring(1) | ||||
|                         artist = &lines.get(2).assume1().substring(1) | ||||
|                         album = &lines.get(3).assume1().substring(1) | ||||
|                         &db.push([index title artist album]) | ||||
|                     } | ||||
|                     Err(string) { | ||||
|                         println("invalid response from server; 3u123128731289") | ||||
|                         exit(1) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             db | ||||
|         } | ||||
|         Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) { | ||||
|             println("couldn't request db from server:") | ||||
|             print("  ") | ||||
|             println(r.to_string()) | ||||
|             exit(1) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| fn get_queue() { | ||||
|     r = make_api_request("ql") | ||||
|     switch! r { | ||||
|         string { | ||||
|             queue = [0 ...] | ||||
|             &queue.remove(0) | ||||
|             for index r.regex("[0-9]+[ \n]").assume_no_enum() { | ||||
|                 &queue.push(index.substring(0 index.len().sub(1)).parse_int().assume1()) | ||||
|             } | ||||
|             queue | ||||
|         } | ||||
|         Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) { | ||||
|             println("couldn't request queue from server:") | ||||
|             print("  ") | ||||
|             println(r.to_string()) | ||||
|             exit(1) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| fn play() { | ||||
|     r = make_api_request("p+") | ||||
|     switch! r { | ||||
|         // success! but nothing to return. | ||||
|         string [] | ||||
|         // return the error | ||||
|         Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r | ||||
|     } | ||||
| } | ||||
| fn stop() { | ||||
|     r = make_api_request("p-") | ||||
|     switch! r { | ||||
|         // success! but nothing to return. | ||||
|         string [] | ||||
|         // return the error | ||||
|         Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r | ||||
|     } | ||||
| } | ||||
| fn queue_song(song_id int) { | ||||
|     make_api_request("q+{0}".format(song_id.to_string())) | ||||
| } | ||||
| 
 | ||||
| // fetch the database contents (a list of songs) | ||||
| database = get_db_contents() | ||||
| 
 | ||||
| // this is where all the songs will be displayed. | ||||
| songs_gui = base.gui_add(Row: []) | ||||
| queue_list = songs_gui.gui_add(Column: []) | ||||
| library = songs_gui.gui_add(Column: []) | ||||
| 
 | ||||
| limit = 0 // set to 0 to disable library length limit | ||||
| for entry database { | ||||
|     // <SONG> by <ARTIST> on <ALBUM> | ||||
|     song = library.gui_add(Row: []) | ||||
|     song.gui_add(Button: entry.1) | ||||
|     song.gui_add(Text: "by {0} on {1}".format(entry.2 entry.3)) | ||||
|     limit = limit.sub(1) | ||||
|     if limit.eq(0) [[]] else [] | ||||
| } | ||||
| 
 | ||||
| // regularly update the queue | ||||
| thread(() { | ||||
|     queue_index = get_queue_index().assume_no_enum("if the server isn't reachable, it's ok to crash") | ||||
|     queue_list_inner = queue_list.gui_add(Column: []) | ||||
|     prev_artist = "" | ||||
|     prev_album = "" | ||||
|     for song_id get_queue() { | ||||
|         this_is_playing = if queue_index.eq(0) { queue_index = -1 true } else if queue_index.gt(0) { queue_index = queue_index.sub(1) false } else { false } | ||||
|         song = &database.get(song_id).assume1() | ||||
|         row = queue_list_inner.gui_add(Row: []) | ||||
|         text = if this_is_playing ">> " else "" | ||||
|         text = text.add(song.1) | ||||
|         if prev_artist.eq(song.2) { | ||||
|             if prev_album.eq(song.3) { | ||||
|             } else { | ||||
|                 text = text.add("(on {0})".format(song.3)) | ||||
|             } | ||||
|         } else { | ||||
|             text = text.add("(by {0} on {1})".format(song.2 song.3)) | ||||
|         } | ||||
|         row.gui_add(Text: text) | ||||
|         [] | ||||
|     } | ||||
|     sleep(10) | ||||
|     queue_list_inner.gui_remove() | ||||
| }) | ||||
| 
 | ||||
| loop { | ||||
|     for event gui_updates() { | ||||
|         switch! event { | ||||
|             ButtonPressed([int ...]) { | ||||
|                 e = event.noenum() | ||||
|                 println("Pressed button {0}".format(e.to_string())) | ||||
|                 match e { | ||||
|                     &e.eq(&play_button) { | ||||
|                         println("pressed play.") | ||||
|                         play() | ||||
|                     } | ||||
|                     &e.eq(&stop_button) { | ||||
|                         println("pressed stop.") | ||||
|                         stop() | ||||
|                     } | ||||
|                     { | ||||
|                         // the button is in a row that is in the library, | ||||
|                         // so pop()ing twice gets the library path. | ||||
|                         // THIS WILL BREAK IF THE GUI LIBRARY SWITCHES TO IDs INSTEAD OF PATHS! | ||||
|                         last = &e.pop().assume1() | ||||
|                         slast = &e.pop().assume1() | ||||
|                         matches = &e.eq(&library) | ||||
|                         &e.push(slast) | ||||
|                         &e.push(last) | ||||
|                         if matches e else [] | ||||
|                     } { | ||||
|                         // the second to last part of the path is the row within library, which is also the index in the db | ||||
|                         song = &database.get(&e.get(e.len().sub(2)).assume1()).assume1() | ||||
|                         println("Added song \"{0}\" to queue.".format(song.1)) | ||||
|                         queue_song(song.0) | ||||
|                     } | ||||
|                     true println("A different button was pressed (unreachable)") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     [] | ||||
| } | ||||
| @ -3,7 +3,17 @@ type myStruct [ | ||||
|     int, | ||||
|     string | ||||
| ] | ||||
| to give names to the fields, we define functions: | ||||
| // to give names to the fields, we define functions: | ||||
| fn count(s myStruct) s.0 | ||||
| // to allow users to change the value, add &myStruct to the valid types for s (only through references can values be changed) | ||||
| fn note(s myStruct/&myStruct) s.1 | ||||
| 
 | ||||
| my_struct := [12, "test"] | ||||
| 
 | ||||
| my_struct.count().debug() | ||||
| 
 | ||||
| my_struct.note().debug() | ||||
| 
 | ||||
| &my_struct.note() = "changed" | ||||
| 
 | ||||
| my_struct.note().debug() | ||||
|  | ||||
							
								
								
									
										2
									
								
								mers/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mers/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -647,7 +647,7 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "mers" | ||||
| version = "0.2.1" | ||||
| version = "0.2.2" | ||||
| dependencies = [ | ||||
|  "colorize", | ||||
|  "edit", | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "mers" | ||||
| version = "0.2.1" | ||||
| version = "0.2.2" | ||||
| edition = "2021" | ||||
| 
 | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
|  | ||||
| @ -636,11 +636,7 @@ impl BuiltinFunction { | ||||
|                                 VSingleType::Tuple(vec![]), | ||||
|                                 VSingleType::Tuple(vec![v | ||||
|                                     .get_any(info) | ||||
|                                     .expect("cannot use get on this type") | ||||
|                                     .dereference(info) | ||||
|                                     .expect( | ||||
|                                         "running get_any() on &[ ...] should give a reference...", | ||||
|                                     )]), | ||||
|                                     .expect("cannot use get on this type")]), | ||||
|                             ], | ||||
|                         } | ||||
|                     } else { | ||||
|  | ||||
| @ -557,7 +557,7 @@ fn statement_adv( | ||||
|         SStatementEnum::For(v, c, b) => { | ||||
|             let mut linfo = linfo.clone(); | ||||
|             let container = statement(&c, ginfo, &mut linfo)?; | ||||
|             let inner = container.out(ginfo).inner_types(ginfo); | ||||
|             let inner = container.out(ginfo).inner_types_for_iters(ginfo); | ||||
|             if inner.types.is_empty() { | ||||
|                 return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes); | ||||
|             } | ||||
| @ -591,7 +591,6 @@ fn statement_adv( | ||||
|                     statement(case_action, ginfo, &mut linfo)?, | ||||
|                 )); | ||||
|             } | ||||
| 
 | ||||
|             if *force { | ||||
|                 let types_not_covered = og_type.fits_in(&covered_types, ginfo); | ||||
|                 if !types_not_covered.is_empty() { | ||||
|  | ||||
| @ -35,70 +35,6 @@ pub enum VSingleType { | ||||
|     CustomTypeS(String), | ||||
| } | ||||
| 
 | ||||
| impl VSingleType { | ||||
|     /// None => Cannot get, Some(t) => getting can return t or nothing
 | ||||
|     pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
|             | Self::Bool | ||||
|             | Self::Int | ||||
|             | Self::Float | ||||
|             | Self::Function(..) | ||||
|             | Self::Thread(..) | ||||
|             | Self::EnumVariant(..) | ||||
|             | Self::EnumVariantS(..) => None, | ||||
|             Self::String => Some(VSingleType::String.into()), | ||||
|             Self::Tuple(t) => t.get(i).cloned(), | ||||
|             Self::List(t) => Some(t.clone()), | ||||
|             Self::Reference(r) => Some(r.get(i, gsinfo)?.reference()), | ||||
|             Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo), | ||||
|             &Self::CustomTypeS(_) => { | ||||
|                 unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     /// None => might not always return t, Some(t) => can only return t
 | ||||
|     pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
|             | Self::Bool | ||||
|             | Self::Int | ||||
|             | Self::Float | ||||
|             | Self::String | ||||
|             | Self::List(_) | ||||
|             | Self::Function(..) | ||||
|             | Self::Thread(..) | ||||
|             | Self::EnumVariant(..) | ||||
|             | Self::EnumVariantS(..) => None, | ||||
|             Self::Tuple(t) => t.get(i).cloned(), | ||||
|             Self::Reference(r) => r.get_always_ref(i, info), | ||||
|             Self::CustomType(t) => info.custom_types[*t].get_always(i, info), | ||||
|             Self::CustomTypeS(_) => { | ||||
|                 unreachable!("CustomTypeS instead of CustomType, compiler bug? [get_always]") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     pub fn get_always_ref(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
|             | Self::Bool | ||||
|             | Self::Int | ||||
|             | Self::Float | ||||
|             | Self::String | ||||
|             | Self::List(_) | ||||
|             | Self::Function(..) | ||||
|             | Self::Thread(..) | ||||
|             | Self::EnumVariant(..) | ||||
|             | Self::EnumVariantS(..) => None, | ||||
|             Self::Tuple(t) => Some(t.get(i)?.reference()), | ||||
|             Self::Reference(r) => r.get_always_ref(i, info), | ||||
|             Self::CustomType(t) => info.custom_types[*t].get_always_ref(i, info), | ||||
|             Self::CustomTypeS(_) => { | ||||
|                 unreachable!("CustomTypeS instead of CustomType, compiler bug? [get_always]") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| impl VType { | ||||
|     pub fn empty() -> Self { | ||||
|         Self { types: vec![] } | ||||
| @ -117,13 +53,6 @@ impl VType { | ||||
|         } | ||||
|         Some(out) | ||||
|     } | ||||
|     pub fn get_always_ref(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         let mut out = VType { types: vec![] }; | ||||
|         for t in &self.types { | ||||
|             out.add_types(t.get_always_ref(i, info)?, info); // if we can't use *get* on one type, we can't use it at all.
 | ||||
|         } | ||||
|         Some(out) | ||||
|     } | ||||
|     /// returns Some(true) or Some(false) if all types are references or not references. If it is mixed or types is empty, returns None.
 | ||||
|     pub fn is_reference(&self) -> Option<bool> { | ||||
|         let mut noref = false; | ||||
| @ -156,6 +85,27 @@ impl VType { | ||||
| } | ||||
| 
 | ||||
| impl VSingleType { | ||||
|     /// None => Cannot get, Some(t) => getting can return t or nothing
 | ||||
|     pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
|             | Self::Bool | ||||
|             | Self::Int | ||||
|             | Self::Float | ||||
|             | Self::Function(..) | ||||
|             | Self::Thread(..) | ||||
|             | Self::EnumVariant(..) | ||||
|             | Self::EnumVariantS(..) => None, | ||||
|             Self::String => Some(VSingleType::String.into()), | ||||
|             Self::Tuple(t) => t.get(i).cloned(), | ||||
|             Self::List(t) => Some(t.clone()), | ||||
|             Self::Reference(r) => Some(r.get(i, gsinfo)?.reference()), | ||||
|             Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo), | ||||
|             &Self::CustomTypeS(_) => { | ||||
|                 unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
| @ -170,33 +120,40 @@ impl VSingleType { | ||||
|                 a | ||||
|             })), | ||||
|             Self::List(t) => Some(t.clone()), | ||||
|             Self::Reference(r) => r.get_any_ref(info), | ||||
|             Self::Reference(r) => Some(VType { | ||||
|                 // this is &a/&b/..., NOT &(a/b/...)!
 | ||||
|                 types: r | ||||
|                     .get_any(info)? | ||||
|                     .types | ||||
|                     .iter() | ||||
|                     .map(|v| VSingleType::Reference(v.clone().to())) | ||||
|                     .collect(), | ||||
|             }), | ||||
|             Self::EnumVariant(_, t) => t.get_any(info), | ||||
|             Self::EnumVariantS(..) => unreachable!(), | ||||
|             Self::CustomType(t) => info.custom_types[*t].get_any(info), | ||||
|             Self::CustomTypeS(_) => unreachable!(), | ||||
|         } | ||||
|     } | ||||
|     pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|     /// None => might not always return t, Some(t) => can only return t
 | ||||
|     pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         match self { | ||||
|             Self::Any | ||||
|             | Self::Bool | ||||
|             | Self::Int | ||||
|             | Self::Float | ||||
|             | Self::String | ||||
|             | Self::List(_) | ||||
|             | Self::Function(..) | ||||
|             | Self::Thread(..) => None, | ||||
|             Self::String => Some(VSingleType::String.into()), | ||||
|             Self::Tuple(t) => Some(t.iter().fold(VType::empty(), |mut a, b| { | ||||
|                 a.add_types(b.reference(), info); | ||||
|                 a | ||||
|             })), | ||||
|             Self::List(t) => Some(t.reference()), | ||||
|             // TODO: idk if this is right...
 | ||||
|             Self::Reference(r) => r.get_any_ref(info), | ||||
|             Self::EnumVariant(_, t) => t.get_any_ref(info), | ||||
|             Self::EnumVariantS(..) => unreachable!(), | ||||
|             Self::CustomType(t) => info.custom_types[*t].get_any(info), | ||||
|             Self::CustomTypeS(_) => unreachable!(), | ||||
|             | Self::Thread(..) | ||||
|             | Self::EnumVariant(..) | ||||
|             | Self::EnumVariantS(..) => None, | ||||
|             Self::Tuple(t) => t.get(i).cloned(), | ||||
|             Self::Reference(r) => Some(VSingleType::Reference(r.get_any(info)?).to()), | ||||
|             Self::CustomType(t) => info.custom_types[*t].get_always(i, info), | ||||
|             Self::CustomTypeS(_) => { | ||||
|                 unreachable!("CustomTypeS instead of CustomType, compiler bug? [get_always]") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     pub fn is_reference(&self) -> bool { | ||||
| @ -221,13 +178,6 @@ impl VType { | ||||
|         } | ||||
|         Some(out) | ||||
|     } | ||||
|     pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> { | ||||
|         let mut out = VType { types: vec![] }; | ||||
|         for t in &self.types { | ||||
|             out.add_types(t.get_any_ref(info)?, info); // if we can't use *get* on one type, we can't use it at all.
 | ||||
|         } | ||||
|         Some(out) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl VType { | ||||
| @ -246,10 +196,10 @@ impl VType { | ||||
|         } | ||||
|         no | ||||
|     } | ||||
|     pub fn inner_types(&self, info: &GlobalScriptInfo) -> VType { | ||||
|     pub fn inner_types_for_iters(&self, info: &GlobalScriptInfo) -> VType { | ||||
|         let mut out = VType { types: vec![] }; | ||||
|         for t in &self.types { | ||||
|             out.add_types(t.inner_types(info), info); | ||||
|             out.add_types(t.inner_types_for_iters(info), info); | ||||
|         } | ||||
|         out | ||||
|     } | ||||
| @ -307,7 +257,7 @@ impl VSingleType { | ||||
|     pub fn to(self) -> VType { | ||||
|         VType { types: vec![self] } | ||||
|     } | ||||
|     pub fn inner_types(&self, info: &GlobalScriptInfo) -> VType { | ||||
|     pub fn inner_types_for_iters(&self, info: &GlobalScriptInfo) -> VType { | ||||
|         match self { | ||||
|             Self::Tuple(v) => { | ||||
|                 let mut out = VType::empty(); | ||||
| @ -324,7 +274,7 @@ impl VSingleType { | ||||
|                 // function that takes no inputs
 | ||||
|                 if let Some(out) = f.iter().find_map(|(args, out)| { | ||||
|                     if args.is_empty() { | ||||
|                         Some(out.clone()) | ||||
|                         Some(out.clone().matches(info).1) | ||||
|                     } else { | ||||
|                         None | ||||
|                     } | ||||
| @ -334,21 +284,7 @@ impl VSingleType { | ||||
|                     VType::empty() | ||||
|                 } | ||||
|             } | ||||
|             Self::Reference(r) => r.inner_types(info).reference(), | ||||
|             _ => VType::empty(), | ||||
|         } | ||||
|     } | ||||
|     pub fn inner_types_ref(&self, info: &GlobalScriptInfo) -> VType { | ||||
|         match self { | ||||
|             Self::Tuple(v) => { | ||||
|                 let mut out = VType::empty(); | ||||
|                 for it in v { | ||||
|                     out.add_types(it.reference(), info); | ||||
|                 } | ||||
|                 out | ||||
|             } | ||||
|             Self::List(v) => v.reference(), | ||||
|             Self::Reference(r) => r.inner_types(info).reference(), | ||||
|             Self::Reference(r) => r.inner_types_for_iters(info).reference(), | ||||
|             _ => VType::empty(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -83,8 +83,6 @@ impl FormatGs for ScriptError { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub const PARSE_VERSION: u64 = 0; | ||||
| 
 | ||||
| pub struct Error { | ||||
|     pub err: ScriptError, | ||||
|     pub ginfo: GSInfo, | ||||
| @ -313,7 +311,6 @@ pub enum ParseErrors { | ||||
|     FoundEofInType, | ||||
|     FoundEofInsteadOfType, | ||||
|     RefTypeWithBracketsNotClosedProperly, | ||||
|     InvalidType(String), | ||||
|     CannotUseFixedIndexingWithThisType(VType), | ||||
|     CannotWrapWithThisStatement(SStatementEnum), | ||||
|     ErrorParsingFunctionArgs(Box<ParseError>), | ||||
| @ -354,7 +351,6 @@ impl FormatGs for ParseErrors { | ||||
|             Self::RefTypeWithBracketsNotClosedProperly => { | ||||
|                 write!(f, "ref type with brackets &(...) wasn't closed properly.") | ||||
|             } | ||||
|             Self::InvalidType(name) => write!(f, "\"{name}\" is not a type."), | ||||
|             Self::CannotUseFixedIndexingWithThisType(t) => { | ||||
|                 write!(f, "cannot use fixed-indexing with type ")?; | ||||
|                 t.fmtgs(f, info, form, file)?; | ||||
| @ -1166,12 +1162,12 @@ pub mod implementation { | ||||
|         } | ||||
|         Ok((VType { types }, closed_fn_args)) | ||||
|     } | ||||
|     fn parse_single_type(file: &mut File) -> Result<VSingleType, ParseError> { | ||||
|         match parse_single_type_adv(file, false) { | ||||
|             Ok((v, _)) => Ok(v), | ||||
|             Err(e) => Err(e), | ||||
|         } | ||||
|     } | ||||
|     // fn parse_single_type(file: &mut File) -> Result<VSingleType, ParseError> {
 | ||||
|     //     match parse_single_type_adv(file, false) {
 | ||||
|     //         Ok((v, _)) => Ok(v),
 | ||||
|     //         Err(e) => Err(e),
 | ||||
|     //     }
 | ||||
|     // }
 | ||||
|     fn parse_single_type_adv( | ||||
|         file: &mut File, | ||||
|         in_fn_args: bool, | ||||
| @ -1277,8 +1273,11 @@ pub mod implementation { | ||||
|                                                     } | ||||
|                                                 } | ||||
|                                                 file.skip_whitespaces(); | ||||
|                                                 let out = parse_type(file)?; | ||||
|                                                 let (out, close) = parse_type_adv(file, true)?; | ||||
|                                                 fn_types.push((args, out)); | ||||
|                                                 if close { | ||||
|                                                     break; | ||||
|                                                 }; | ||||
|                                             } | ||||
|                                             Some(')') => break, | ||||
|                                             Some(other) => { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 mark
						mark