scanner: add support for @VMOD_FILE
							parent
							
								
									bb48851092
								
							
						
					
					
						commit
						3cfdd2a4cd
					
				
							
								
								
									
										26
									
								
								doc/docs.md
								
								
								
								
							
							
						
						
									
										26
									
								
								doc/docs.md
								
								
								
								
							|  | @ -1622,6 +1622,32 @@ $if debug { | ||||||
| If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign. Right now it can only be used to detect | If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign. Right now it can only be used to detect | ||||||
| an OS or a `-debug` compilation option. | an OS or a `-debug` compilation option. | ||||||
| 
 | 
 | ||||||
|  | ## Compile time pseudo variables | ||||||
|  | 
 | ||||||
|  | V also gives your code access to a set of pseudo string variables, that are substituted at compile time: | ||||||
|  | 
 | ||||||
|  | - `@FN` => replaced with the name of the current V function | ||||||
|  | - `@MOD` => replaced with the name of the current V module | ||||||
|  | - `@STRUCT` => replaced with the name of the current V struct | ||||||
|  | - `@FILE` => replaced with the path of the V source file | ||||||
|  | - `@LINE` => replaced with the V line number where it appears (as a string). | ||||||
|  | - `@COLUMN` => replaced with the column where it appears (as a string). | ||||||
|  | - `@VEXE` => replaced with the path to the V compiler | ||||||
|  | - `@VHASH`  => replaced with the shortened commit hash of the V compiler (as a string). | ||||||
|  | - `@VMOD_FILE` => replaced with the contents of the nearest v.mod file (as a string). | ||||||
|  | 
 | ||||||
|  | That allows you to do the following example, useful while debugging/logging/tracing your code: | ||||||
|  | ```v | ||||||
|  | eprintln( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Another example, is if you want to embed the version/name from v.mod *inside* your executable: | ||||||
|  | ```v | ||||||
|  | import v.vmod | ||||||
|  | vm := vmod.decode( @VMOD_FILE ) or { panic(err) } | ||||||
|  | eprintln('$vm.name $vm.version\n $vm.description') | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Reflection via codegen | ## Reflection via codegen | ||||||
| 
 | 
 | ||||||
| Having built-in JSON support is nice, but V also allows you to create efficient | Having built-in JSON support is nice, but V also allows you to create efficient | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import os | ||||||
| import v.token | import v.token | ||||||
| import v.pref | import v.pref | ||||||
| import v.util | import v.util | ||||||
|  | import v.vmod | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	single_quote = `\'` | 	single_quote = `\'` | ||||||
|  | @ -32,6 +33,7 @@ pub mut: | ||||||
| 	fn_name                     string // needed for @FN
 | 	fn_name                     string // needed for @FN
 | ||||||
| 	mod_name                    string // needed for @MOD
 | 	mod_name                    string // needed for @MOD
 | ||||||
| 	struct_name                 string // needed for @STRUCT
 | 	struct_name                 string // needed for @STRUCT
 | ||||||
|  | 	vmod_file_content           string // needed for @VMOD_FILE, contents of the file, *NOT its path*
 | ||||||
| 	is_print_line_on_error      bool | 	is_print_line_on_error      bool | ||||||
| 	is_print_colored_error      bool | 	is_print_colored_error      bool | ||||||
| 	is_print_rel_paths_on_error bool | 	is_print_rel_paths_on_error bool | ||||||
|  | @ -745,6 +747,7 @@ pub fn (mut s Scanner) scan() token.Token { | ||||||
| 			// @LINE => will be substituted with the V line number where it appears (as a string).
 | 			// @LINE => will be substituted with the V line number where it appears (as a string).
 | ||||||
| 			// @COLUMN => will be substituted with the column where it appears (as a string).
 | 			// @COLUMN => will be substituted with the column where it appears (as a string).
 | ||||||
| 			// @VHASH  => will be substituted with the shortened commit hash of the V compiler (as a string).
 | 			// @VHASH  => will be substituted with the shortened commit hash of the V compiler (as a string).
 | ||||||
|  | 			// @VMOD_FILE => will be substituted with the contents of the nearest v.mod file (as a string).
 | ||||||
| 			// This allows things like this:
 | 			// This allows things like this:
 | ||||||
| 			// println( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
 | 			// println( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
 | ||||||
| 			// ... which is useful while debugging/tracing
 | 			// ... which is useful while debugging/tracing
 | ||||||
|  | @ -773,6 +776,17 @@ pub fn (mut s Scanner) scan() token.Token { | ||||||
| 			if name == 'VHASH' { | 			if name == 'VHASH' { | ||||||
| 				return s.new_token(.string, util.vhash(), 6) | 				return s.new_token(.string, util.vhash(), 6) | ||||||
| 			} | 			} | ||||||
|  | 			if name == 'VMOD_FILE' { | ||||||
|  | 				if s.vmod_file_content.len == 0 { | ||||||
|  | 					vmod_file_location := vmod.mod_file_cacher.get( os.dir( os.real_path(s.file_path) ) ) | ||||||
|  | 					if vmod_file_location.vmod_file.len == 0 { | ||||||
|  | 						s.error('@VMOD_FILE can be used only in projects, that have v.mod file') | ||||||
|  | 					} | ||||||
|  | 					vmod_content := os.read_file(vmod_file_location.vmod_file) or {''} | ||||||
|  | 					s.vmod_file_content = vmod_content | ||||||
|  | 				} | ||||||
|  | 				return s.new_token(.string, s.vmod_file_content, 10) | ||||||
|  | 			} | ||||||
| 			if !token.is_key(name) { | 			if !token.is_key(name) { | ||||||
| 				s.error('@ must be used before keywords (e.g. `@type string`)') | 				s.error('@ must be used before keywords (e.g. `@type string`)') | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -82,3 +82,12 @@ fn test_scan() { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn test_vmod_file() { | ||||||
|  | 	content := @VMOD_FILE | ||||||
|  | 	assert content.len > 0 | ||||||
|  | 	assert content.contains('Module {') | ||||||
|  | 	assert content.contains('name:') | ||||||
|  | 	assert content.contains('version:') | ||||||
|  | 	assert content.contains('description:') | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue