Merge branch 'master' into unsigned-eq
commit
f8ae042eb9
|
|
@ -306,13 +306,15 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
mut run_js := false
|
mut run_js := false
|
||||||
|
|
||||||
is_fmt := ts.vargs.contains('fmt')
|
is_fmt := ts.vargs.contains('fmt')
|
||||||
|
is_vet := ts.vargs.contains('vet')
|
||||||
|
produces_file_output := !(is_fmt || is_vet)
|
||||||
|
|
||||||
if relative_file.ends_with('js.v') {
|
if relative_file.ends_with('js.v') {
|
||||||
if !is_fmt {
|
if produces_file_output {
|
||||||
cmd_options << ' -b js'
|
cmd_options << ' -b js'
|
||||||
}
|
|
||||||
run_js = true
|
run_js = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if relative_file.contains('global') && !is_fmt {
|
if relative_file.contains('global') && !is_fmt {
|
||||||
cmd_options << ' -enable-globals'
|
cmd_options << ' -enable-globals'
|
||||||
|
|
@ -333,13 +335,13 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
fname.replace('.v', '')
|
fname.replace('.v', '')
|
||||||
}
|
}
|
||||||
generated_binary_fpath := os.join_path_single(tmpd, generated_binary_fname)
|
generated_binary_fpath := os.join_path_single(tmpd, generated_binary_fname)
|
||||||
|
if produces_file_output {
|
||||||
if os.exists(generated_binary_fpath) {
|
if os.exists(generated_binary_fpath) {
|
||||||
if ts.rm_binaries {
|
if ts.rm_binaries {
|
||||||
os.rm(generated_binary_fpath) or {}
|
os.rm(generated_binary_fpath) or {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ts.vargs.contains('fmt') {
|
|
||||||
cmd_options << ' -o ${os.quoted_path(generated_binary_fpath)}'
|
cmd_options << ' -o ${os.quoted_path(generated_binary_fpath)}'
|
||||||
}
|
}
|
||||||
cmd := '${os.quoted_path(ts.vexe)} ' + cmd_options.join(' ') + ' ${os.quoted_path(file)}'
|
cmd := '${os.quoted_path(ts.vexe)} ' + cmd_options.join(' ') + ' ${os.quoted_path(file)}'
|
||||||
|
|
@ -421,11 +423,9 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if os.exists(generated_binary_fpath) {
|
if produces_file_output && os.exists(generated_binary_fpath) && ts.rm_binaries {
|
||||||
if ts.rm_binaries {
|
|
||||||
os.rm(generated_binary_fpath) or {}
|
os.rm(generated_binary_fpath) or {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return pool.no_result
|
return pool.no_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,13 +247,9 @@ fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_pa
|
||||||
if !is_formatted_different {
|
if !is_formatted_different {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
x := diff.color_compare_files(foptions.find_diff_cmd(), file, formatted_file_path)
|
|
||||||
if x.len != 0 {
|
|
||||||
println("$file is not vfmt'ed")
|
println("$file is not vfmt'ed")
|
||||||
return error('')
|
return error('')
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
if foptions.is_c {
|
if foptions.is_c {
|
||||||
if is_formatted_different {
|
if is_formatted_different {
|
||||||
eprintln('File is not formatted: $file')
|
eprintln('File is not formatted: $file')
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,12 @@ fn main() {
|
||||||
module_names = manifest.dependencies
|
module_names = manifest.dependencies
|
||||||
}
|
}
|
||||||
mut source := Source.vpm
|
mut source := Source.vpm
|
||||||
|
if '--once' in options {
|
||||||
|
module_names = vpm_once_filter(module_names)
|
||||||
|
if module_names.len == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if '--git' in options {
|
if '--git' in options {
|
||||||
source = Source.git
|
source = Source.git
|
||||||
}
|
}
|
||||||
|
|
@ -327,6 +333,17 @@ fn vpm_install_from_vcs(module_names []string, vcs_key string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vpm_once_filter(module_names []string) []string {
|
||||||
|
installed_modules := get_installed_modules()
|
||||||
|
mut toinstall := []string{}
|
||||||
|
for mn in module_names {
|
||||||
|
if mn !in installed_modules {
|
||||||
|
toinstall << mn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toinstall
|
||||||
|
}
|
||||||
|
|
||||||
fn vpm_install(module_names []string, source Source) {
|
fn vpm_install(module_names []string, source Source) {
|
||||||
if settings.is_help {
|
if settings.is_help {
|
||||||
vhelp.show_topic('install')
|
vhelp.show_topic('install')
|
||||||
|
|
@ -336,16 +353,17 @@ fn vpm_install(module_names []string, source Source) {
|
||||||
println('´v install´ requires *at least one* module name.')
|
println('´v install´ requires *at least one* module name.')
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
|
match source {
|
||||||
if source == .vpm {
|
.vpm {
|
||||||
vpm_install_from_vpm(module_names)
|
vpm_install_from_vpm(module_names)
|
||||||
}
|
}
|
||||||
if source == .git {
|
.git {
|
||||||
vpm_install_from_vcs(module_names, 'git')
|
vpm_install_from_vcs(module_names, 'git')
|
||||||
}
|
}
|
||||||
if source == .hg {
|
.hg {
|
||||||
vpm_install_from_vcs(module_names, 'hg')
|
vpm_install_from_vcs(module_names, 'hg')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vpm_update(m []string) {
|
fn vpm_update(m []string) {
|
||||||
|
|
@ -445,12 +463,11 @@ fn vpm_outdated() {
|
||||||
fn vpm_list() {
|
fn vpm_list() {
|
||||||
module_names := get_installed_modules()
|
module_names := get_installed_modules()
|
||||||
if module_names.len == 0 {
|
if module_names.len == 0 {
|
||||||
println('You have no modules installed.')
|
eprintln('You have no modules installed.')
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
println('Installed modules:')
|
|
||||||
for mod in module_names {
|
for mod in module_names {
|
||||||
println(' $mod')
|
println(mod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Options:
|
||||||
--vpm - [Default] Install from vpm
|
--vpm - [Default] Install from vpm
|
||||||
--git - Install from git repository url
|
--git - Install from git repository url
|
||||||
--hg - Install from mercurial repository url
|
--hg - Install from mercurial repository url
|
||||||
|
--once - Only install the module if it was not previously installed
|
||||||
-help - Show usage info.
|
-help - Show usage info.
|
||||||
-v - Print more details about the performed operation.
|
-v - Print more details about the performed operation.
|
||||||
-server-url - When doing network operations, use this vpm server. Can be given multiple times.
|
-server-url - When doing network operations, use this vpm server. Can be given multiple times.
|
||||||
|
|
|
||||||
13
doc/docs.md
13
doc/docs.md
|
|
@ -26,6 +26,8 @@ git clone https://github.com/vlang/v
|
||||||
cd v
|
cd v
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
See [here](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Linux-and-macOS)
|
||||||
|
for how to install the development tools.
|
||||||
|
|
||||||
### Windows:
|
### Windows:
|
||||||
You need `git`, and a C compiler like `tcc`, `gcc`, `clang` or `msvc`:
|
You need `git`, and a C compiler like `tcc`, `gcc`, `clang` or `msvc`:
|
||||||
|
|
@ -38,6 +40,9 @@ NB: You can also pass one of `-gcc`, `-msvc`, `-clang` to `make.bat` instead,
|
||||||
if you do prefer to use a different C compiler, but -tcc is small, fast, and
|
if you do prefer to use a different C compiler, but -tcc is small, fast, and
|
||||||
easy to install (V will download a prebuilt binary automatically).
|
easy to install (V will download a prebuilt binary automatically).
|
||||||
|
|
||||||
|
For C compiler downloads and more info, see
|
||||||
|
[here](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows).
|
||||||
|
|
||||||
It is recommended to add this folder to the PATH of your environment variables.
|
It is recommended to add this folder to the PATH of your environment variables.
|
||||||
This can be done with the command `v.exe symlink`.
|
This can be done with the command `v.exe symlink`.
|
||||||
|
|
||||||
|
|
@ -4601,13 +4606,19 @@ v install ui
|
||||||
|
|
||||||
Modules can be installed directly from git or mercurial repositories.
|
Modules can be installed directly from git or mercurial repositories.
|
||||||
```powershell
|
```powershell
|
||||||
v install [--git|--hg] [url]
|
v install [--once] [--git|--hg] [url]
|
||||||
```
|
```
|
||||||
**Example:**
|
**Example:**
|
||||||
```powershell
|
```powershell
|
||||||
v install --git https://github.com/vlang/markdown
|
v install --git https://github.com/vlang/markdown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Sometimes you may want to install the dependencies **ONLY** if those are not installed:
|
||||||
|
|
||||||
|
```
|
||||||
|
v install --once [module]
|
||||||
|
```
|
||||||
|
|
||||||
Removing a module with v:
|
Removing a module with v:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,10 @@ fn main() {
|
||||||
println('failed to fetch data from /v0/topstories.json')
|
println('failed to fetch data from /v0/topstories.json')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mut ids := json.decode([]int, resp.text) or {
|
ids := json.decode([]int, resp.text) or {
|
||||||
println('failed to decode topstories.json')
|
println('failed to decode topstories.json')
|
||||||
return
|
return
|
||||||
}
|
}#[0..10]
|
||||||
if ids.len > 10 {
|
|
||||||
ids = ids[0..10]
|
|
||||||
}
|
|
||||||
mut fetcher_pool := pool.new_pool_processor(
|
mut fetcher_pool := pool.new_pool_processor(
|
||||||
callback: worker_fetch
|
callback: worker_fetch
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
title := 'Sokol Drawing Template'
|
title := 'Sokol Drawing Template'
|
||||||
desc := sapp.Desc{
|
desc := sapp.Desc{
|
||||||
|
width: 640
|
||||||
|
height: 480
|
||||||
user_data: state
|
user_data: state
|
||||||
init_userdata_cb: init
|
init_userdata_cb: init
|
||||||
frame_userdata_cb: frame
|
frame_userdata_cb: frame
|
||||||
|
|
@ -49,9 +51,9 @@ fn draw() {
|
||||||
sgl.matrix_mode_projection()
|
sgl.matrix_mode_projection()
|
||||||
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
||||||
sgl.c4b(255, 0, 0, 128)
|
sgl.c4b(255, 0, 0, 128)
|
||||||
draw_hollow_rect(10, 10, 100, 30)
|
draw_hollow_rect(220, 140, 200, 200)
|
||||||
sgl.c4b(25, 150, 0, 128)
|
sgl.c4b(25, 150, 255, 128)
|
||||||
draw_filled_rect(10, 150, 80, 40)
|
draw_filled_rect(270, 190, 100, 100)
|
||||||
// line(0, 0, 500, 500)
|
// line(0, 0, 500, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,3 +293,10 @@ fn test_can_copy_bits() {
|
||||||
// map not copyable
|
// map not copyable
|
||||||
assert !can_copy_bits<map[string]int>()
|
assert !can_copy_bits<map[string]int>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Str = string
|
||||||
|
|
||||||
|
fn test_alias_string_contains() {
|
||||||
|
names := [Str('')]
|
||||||
|
assert (Str('') in names) == true
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ fn (mut cb Clipboard) start_listener() {
|
||||||
property: xsre.property
|
property: xsre.property
|
||||||
}
|
}
|
||||||
if !cb.transmit_selection(&xse) {
|
if !cb.transmit_selection(&xse) {
|
||||||
xse.property = new_atom(0)
|
xse.property = Atom(0)
|
||||||
}
|
}
|
||||||
C.XSendEvent(cb.display, xse.requestor, 0, C.PropertyChangeMask, voidptr(&xse))
|
C.XSendEvent(cb.display, xse.requestor, 0, C.PropertyChangeMask, voidptr(&xse))
|
||||||
C.XFlush(cb.display)
|
C.XFlush(cb.display)
|
||||||
|
|
@ -479,10 +479,6 @@ fn (cb &Clipboard) get_supported_targets() []Atom {
|
||||||
return cb.get_atoms(AtomType.utf8_string, .xa_string, .text, .text_plain, .text_html)
|
return cb.get_atoms(AtomType.utf8_string, .xa_string, .text, .text_plain, .text_html)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_atom(value int) &Atom {
|
|
||||||
return unsafe { &Atom(&u64(u64(value))) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_xwindow(display &C.Display) Window {
|
fn create_xwindow(display &C.Display) Window {
|
||||||
n := C.DefaultScreen(display)
|
n := C.DefaultScreen(display)
|
||||||
return C.XCreateSimpleWindow(display, C.RootWindow(display, n), 0, 0, 1, 1, 0, C.BlackPixel(display,
|
return C.XCreateSimpleWindow(display, C.RootWindow(display, n), 0, 0, 1, 1, 0, C.BlackPixel(display,
|
||||||
|
|
|
||||||
|
|
@ -24,25 +24,34 @@ pub type Context = C.FONScontext
|
||||||
pub const (
|
pub const (
|
||||||
// TODO: fontstash.used_import is used to keep v from warning about unused imports
|
// TODO: fontstash.used_import is used to keep v from warning about unused imports
|
||||||
used_import = 1
|
used_import = 1
|
||||||
|
invalid = C.FONS_INVALID // -1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Contructor and destructor.
|
// create_internal returns a fontstash Context allocated on the heap.
|
||||||
|
//
|
||||||
|
// See also: delete_internal
|
||||||
[inline]
|
[inline]
|
||||||
pub fn create_internal(params &C.FONSparams) &Context {
|
pub fn create_internal(params &C.FONSparams) &Context {
|
||||||
return C.fonsCreateInternal(params)
|
return C.fonsCreateInternal(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete_internal deletes and free memory of `s` fontstash Context.
|
||||||
|
//
|
||||||
|
// See also: create_internal
|
||||||
[inline]
|
[inline]
|
||||||
pub fn delete_internal(s &Context) {
|
pub fn delete_internal(s &Context) {
|
||||||
C.fonsDeleteInternal(s)
|
C.fonsDeleteInternal(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_error_callback sets `callback` as a function to be called if fontstash
|
||||||
|
// encounter any errors. `uptr` can be used to pass custom userdata.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_error_callback(callback fn (voidptr, int, int), uptr voidptr) {
|
pub fn (s &Context) set_error_callback(callback fn (voidptr, int, int), uptr voidptr) {
|
||||||
C.fonsSetErrorCallback(s, callback, uptr)
|
C.fonsSetErrorCallback(s, callback, uptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns current atlas size.
|
// get_atlas_size returns the current size of the texture atlas which
|
||||||
|
// the font is rendered to.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) get_atlas_size() (int, int) {
|
pub fn (s &Context) get_atlas_size() (int, int) {
|
||||||
mut width := 0
|
mut width := 0
|
||||||
|
|
@ -51,126 +60,203 @@ pub fn (s &Context) get_atlas_size() (int, int) {
|
||||||
return width, height
|
return width, height
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expands the atlas size.
|
// expand_atlas expands the font texture atlas size to `width` x `height`.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) expand_atlas(width int, height int) int {
|
pub fn (s &Context) expand_atlas(width int, height int) int {
|
||||||
return C.fonsExpandAtlas(s, width, height)
|
return C.fonsExpandAtlas(s, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the whole stash.
|
// reset_atlas resets `width` x `height` of the font texture atlas.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) reset_atlas(width int, height int) int {
|
pub fn (s &Context) reset_atlas(width int, height int) int {
|
||||||
return C.fonsResetAtlas(s, width, height)
|
return C.fonsResetAtlas(s, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add fonts
|
// get_font_by_name returns the id of the font with `name` or
|
||||||
|
// `fontstash.invalid` if no font with `name` could be found.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) get_font_by_name(name string) int {
|
pub fn (s &Context) get_font_by_name(name string) int {
|
||||||
return C.fonsGetFontByName(s, &char(name.str))
|
return C.fonsGetFontByName(s, &char(name.str))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add_fallback_font adds a fallback font to the `base` font id in the Context.
|
||||||
|
// `fallback` is expected to be the id of a previous, successfully, added font.
|
||||||
|
// add_fallback_font returns `1` on success, `0` otherwise.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) add_fallback_font(base int, fallback int) int {
|
pub fn (s &Context) add_fallback_font(base int, fallback int) int {
|
||||||
return C.fonsAddFallbackFont(s, base, fallback)
|
return C.fonsAddFallbackFont(s, base, fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add_font_mem adds the font data located in memory to the Context.
|
||||||
|
// `name` is the human readable name for the font.
|
||||||
|
// `free_data` indicates if `data` should be freed after the font is added.
|
||||||
|
// The function returns the id of the font on success, `fontstash.invalid` otherwise.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) add_font_mem(name string, data []byte, free_data bool) int {
|
pub fn (s &Context) add_font_mem(name string, data []byte, free_data bool) int {
|
||||||
return C.fonsAddFontMem(s, &char(name.str), data.data, data.len, int(free_data))
|
return C.fonsAddFontMem(s, &char(name.str), data.data, data.len, int(free_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// State handling
|
// push_state pushes a new state on the state stack.
|
||||||
|
// A state holds the current attributes of the rendering,
|
||||||
|
// attributes are things like color, size, the font in use, blur effect etc.
|
||||||
|
//
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
|
// See also: set_size
|
||||||
|
// See also: set_color
|
||||||
|
// See also: set_spacing
|
||||||
|
// See also: set_blur
|
||||||
|
// See also: set_align
|
||||||
|
// See also: set_font
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) push_state() {
|
pub fn (s &Context) push_state() {
|
||||||
C.fonsPushState(s)
|
C.fonsPushState(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pop_state pops the current state from the state stack.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) pop_state() {
|
pub fn (s &Context) pop_state() {
|
||||||
C.fonsPopState(s)
|
C.fonsPopState(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear_state clears the current state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) clear_state() {
|
pub fn (s &Context) clear_state() {
|
||||||
C.fonsClearState(s)
|
C.fonsClearState(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// State setting
|
// set_size sets the font size to `size` on the active state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_size(size f32) {
|
pub fn (s &Context) set_size(size f32) {
|
||||||
C.fonsSetSize(s, size)
|
C.fonsSetSize(s, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_color sets the font color to `color` on the active state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_color(color u32) {
|
pub fn (s &Context) set_color(color u32) {
|
||||||
C.fonsSetColor(s, color)
|
C.fonsSetColor(s, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_spacing sets the font spacing to `spacing` on the active state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_spacing(spacing f32) {
|
pub fn (s &Context) set_spacing(spacing f32) {
|
||||||
C.fonsSetSpacing(s, spacing)
|
C.fonsSetSpacing(s, spacing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_blur sets the font blur effect to `blur` on the active state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_blur(blur f32) {
|
pub fn (s &Context) set_blur(blur f32) {
|
||||||
C.fonsSetBlur(s, blur)
|
C.fonsSetBlur(s, blur)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_align sets the font aligning to `align` on the active state.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_align(align int) {
|
pub fn (s &Context) set_align(align int) {
|
||||||
C.fonsSetAlign(s, align)
|
C.fonsSetAlign(s, align)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_font sets the font used for this render on the active state.
|
||||||
|
// `font_id` is the id of the loaded font.
|
||||||
|
//
|
||||||
|
// See also: push_state
|
||||||
|
// See also: pop_state
|
||||||
|
// See also: clear_state
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) set_font(font int) {
|
pub fn (s &Context) set_font(font_id int) {
|
||||||
C.fonsSetFont(s, font)
|
C.fonsSetFont(s, font_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text
|
// draw_text draws the `text` string at position `x`,`y`.
|
||||||
|
// The function returns the `x` coordinate of the resulting render.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) draw_text(x f32, y f32, text string) f32 {
|
pub fn (s &Context) draw_text(x f32, y f32, text string) f32 {
|
||||||
return C.fonsDrawText(s, x, y, &char(text.str), &char(0))
|
return C.fonsDrawText(s, x, y, &char(text.str), &char(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure text
|
// text_bounds fills the `bounds` argument with the pixel dimensions
|
||||||
|
// of the rendered `text` at position `x`,`y`.
|
||||||
|
//
|
||||||
|
// `bounds` is expected to be of type `mut bounds := [4]f32{}`.
|
||||||
|
// Call example: `ctx.text_bounds(0, 0, 'example', &bounds[0])`.
|
||||||
|
// `bounds[0]` is the `x` coordinate of the top-left point.
|
||||||
|
// `bounds[1]` is the `y` coordinate of the top-left point.
|
||||||
|
// `bounds[2]` is the `x` coordinate of the bottom-right point.
|
||||||
|
// `bounds[3]` is the `y` coordinate of the bottom-right point.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) text_bounds(x f32, y f32, text string, bounds &f32) f32 {
|
pub fn (s &Context) text_bounds(x f32, y f32, text string, bounds &f32) f32 {
|
||||||
return C.fonsTextBounds(s, x, y, &char(text.str), &char(0), bounds)
|
return C.fonsTextBounds(s, x, y, &char(text.str), &char(0), bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// line_bounds fills `miny` and `maxy` with the values of the `minimum`
|
||||||
|
// and `maximum` line bounds respectively.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) line_bounds(y f32, miny &f32, maxy &f32) {
|
pub fn (s &Context) line_bounds(y f32, miny &f32, maxy &f32) {
|
||||||
C.fonsLineBounds(s, y, miny, maxy)
|
C.fonsLineBounds(s, y, miny, maxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vert_metrics assigns the respective values of `ascender`, `descender` and `lineh`.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) vert_metrics(ascender &f32, descender &f32, lineh &f32) {
|
pub fn (s &Context) vert_metrics(ascender &f32, descender &f32, lineh &f32) {
|
||||||
C.fonsVertMetrics(s, ascender, descender, lineh)
|
C.fonsVertMetrics(s, ascender, descender, lineh)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text iterator
|
// text_iter_init initalizes the text iterator `iter`.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) text_iter_init(iter &C.FONStextIter, x f32, y f32, str &char, end &char) int {
|
pub fn (s &Context) text_iter_init(iter &C.FONStextIter, x f32, y f32, str &char, end &char) int {
|
||||||
return C.fonsTextIterInit(s, iter, x, y, str, end)
|
return C.fonsTextIterInit(s, iter, x, y, str, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// text_iter_next advances `iter` to the next `quad`.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) text_iter_next(iter &C.FONStextIter, quad &C.FONSquad) int {
|
pub fn (s &Context) text_iter_next(iter &C.FONStextIter, quad &C.FONSquad) int {
|
||||||
return C.fonsTextIterNext(s, iter, quad)
|
return C.fonsTextIterNext(s, iter, quad)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull texture changes
|
// get_texture_data returns the current Context's raw texture data.
|
||||||
|
// `width` and `height` is assigned the size of the texture dimensions.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) get_texture_data(width &int, height &int) &byte {
|
pub fn (s &Context) get_texture_data(width &int, height &int) &byte {
|
||||||
return &byte(C.fonsGetTextureData(s, width, height))
|
return &byte(C.fonsGetTextureData(s, width, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate_texture fills the `dirty` argument with the pixel dimensions
|
||||||
|
// of the dirty rectangle of the Context's raw texture, if any.
|
||||||
|
//
|
||||||
|
// `dirty` is expected to be of type `mut dirty := [4]int{}`.
|
||||||
|
// Call example: `is_dirty := ctx.validate_texture(&dirty[0])`.
|
||||||
|
// The function returns `1` if the texture has a dirty rectangle, `0` otherwise.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) validate_texture(dirty &int) int {
|
pub fn (s &Context) validate_texture(dirty &int) int {
|
||||||
return C.fonsValidateTexture(s, dirty)
|
return C.fonsValidateTexture(s, dirty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws the stash texture for debugging
|
// draw_debug draws the stash texture for debugging.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (s &Context) draw_debug(x f32, y f32) {
|
pub fn (s &Context) draw_debug(x f32, y f32) {
|
||||||
C.fonsDrawDebug(s, x, y)
|
C.fonsDrawDebug(s, x, y)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
struct DbConfig {
|
struct DbConfig {}
|
||||||
foo int
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_json_decode_with_optional_arg() {
|
fn test_json_decode_with_optional_arg() {
|
||||||
if ret := print_info() {
|
if ret := print_info() {
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,10 @@ pub fn execute(cmd string) Result {
|
||||||
// if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
// if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
||||||
// return Result{ exit_code: -1, output: ';, &&, || and \\n are not allowed in shell commands' }
|
// return Result{ exit_code: -1, output: ';, &&, || and \\n are not allowed in shell commands' }
|
||||||
// }
|
// }
|
||||||
pcmd := if cmd.contains('2>') { cmd } else { '$cmd 2>&1' }
|
pcmd := if cmd.contains('2>') { cmd.clone() } else { '$cmd 2>&1' }
|
||||||
|
defer {
|
||||||
|
unsafe { pcmd.free() }
|
||||||
|
}
|
||||||
f := vpopen(pcmd)
|
f := vpopen(pcmd)
|
||||||
if isnil(f) {
|
if isnil(f) {
|
||||||
return Result{
|
return Result{
|
||||||
|
|
|
||||||
|
|
@ -144,24 +144,25 @@ pub fn (mut rng MT19937RNG) u32() u32 {
|
||||||
return u32(ans)
|
return u32(ans)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mag01 = [u64(0), u64(matrix_a)]
|
||||||
|
|
||||||
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
|
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
|
||||||
[inline]
|
[direct_array_access; inline]
|
||||||
pub fn (mut rng MT19937RNG) u64() u64 {
|
pub fn (mut rng MT19937RNG) u64() u64 {
|
||||||
mag01 := [u64(0), u64(mt19937.matrix_a)]
|
|
||||||
mut x := u64(0)
|
mut x := u64(0)
|
||||||
mut i := int(0)
|
mut i := int(0)
|
||||||
if rng.mti >= mt19937.nn {
|
if rng.mti >= mt19937.nn {
|
||||||
for i = 0; i < mt19937.nn - mt19937.mm; i++ {
|
for i = 0; i < mt19937.nn - mt19937.mm; i++ {
|
||||||
x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
|
x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
|
||||||
rng.state[i] = rng.state[i + mt19937.mm] ^ (x >> 1) ^ mag01[int(x & 1)]
|
rng.state[i] = rng.state[i + mt19937.mm] ^ (x >> 1) ^ mt19937.mag01[int(x & 1)]
|
||||||
}
|
}
|
||||||
for i < mt19937.nn - 1 {
|
for i < mt19937.nn - 1 {
|
||||||
x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
|
x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
|
||||||
rng.state[i] = rng.state[i + (mt19937.mm - mt19937.nn)] ^ (x >> 1) ^ mag01[int(x & 1)]
|
rng.state[i] = rng.state[i + (mt19937.mm - mt19937.nn)] ^ (x >> 1) ^ mt19937.mag01[int(x & 1)]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
x = (rng.state[mt19937.nn - 1] & mt19937.um) | (rng.state[0] & mt19937.lm)
|
x = (rng.state[mt19937.nn - 1] & mt19937.um) | (rng.state[0] & mt19937.lm)
|
||||||
rng.state[mt19937.nn - 1] = rng.state[mt19937.mm - 1] ^ (x >> 1) ^ mag01[int(x & 1)]
|
rng.state[mt19937.nn - 1] = rng.state[mt19937.mm - 1] ^ (x >> 1) ^ mt19937.mag01[int(x & 1)]
|
||||||
rng.mti = 0
|
rng.mti = 0
|
||||||
}
|
}
|
||||||
x = rng.state[rng.mti]
|
x = rng.state[rng.mti]
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ pub fn (mut rng MuslRNG) seed(seed_data []u32) {
|
||||||
|
|
||||||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||||
[inline]
|
[inline]
|
||||||
fn (mut rng MuslRNG) byte() byte {
|
pub fn (mut rng MuslRNG) byte() byte {
|
||||||
if rng.bytes_left >= 1 {
|
if rng.bytes_left >= 1 {
|
||||||
rng.bytes_left -= 1
|
rng.bytes_left -= 1
|
||||||
value := byte(rng.buffer)
|
value := byte(rng.buffer)
|
||||||
|
|
@ -70,7 +70,7 @@ fn temper(prev u32) u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// u32 returns a pseudorandom 32-bit unsigned integer (`u32`).
|
// u32 returns a pseudorandom 32-bit unsigned integer (`u32`).
|
||||||
fn (mut rng MuslRNG) u32() u32 {
|
pub fn (mut rng MuslRNG) u32() u32 {
|
||||||
rng.state = rng.state * 1103515245 + 12345
|
rng.state = rng.state * 1103515245 + 12345
|
||||||
// We are not dividing by 2 (or shifting right by 1)
|
// We are not dividing by 2 (or shifting right by 1)
|
||||||
// because we want all 32-bits of random data
|
// because we want all 32-bits of random data
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ pub fn (mut rng PCG32RNG) seed(seed_data []u32) {
|
||||||
|
|
||||||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||||
[inline]
|
[inline]
|
||||||
fn (mut rng PCG32RNG) byte() byte {
|
pub fn (mut rng PCG32RNG) byte() byte {
|
||||||
if rng.bytes_left >= 1 {
|
if rng.bytes_left >= 1 {
|
||||||
rng.bytes_left -= 1
|
rng.bytes_left -= 1
|
||||||
value := byte(rng.buffer)
|
value := byte(rng.buffer)
|
||||||
|
|
@ -70,7 +70,7 @@ pub fn (mut rng PCG32RNG) u16() u16 {
|
||||||
|
|
||||||
// u32 returns a pseudorandom unsigned `u32`.
|
// u32 returns a pseudorandom unsigned `u32`.
|
||||||
[inline]
|
[inline]
|
||||||
fn (mut rng PCG32RNG) u32() u32 {
|
pub fn (mut rng PCG32RNG) u32() u32 {
|
||||||
oldstate := rng.state
|
oldstate := rng.state
|
||||||
rng.state = oldstate * (6364136223846793005) + rng.inc
|
rng.state = oldstate * (6364136223846793005) + rng.inc
|
||||||
xorshifted := u32(((oldstate >> u64(18)) ^ oldstate) >> u64(27))
|
xorshifted := u32(((oldstate >> u64(18)) ^ oldstate) >> u64(27))
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,47 @@
|
||||||
module strconv
|
module strconv
|
||||||
|
|
||||||
/*
|
// Copyright (c) 2019-2022 Dario Deledda. All rights reserved.
|
||||||
atof util
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// This file contains utilities for converting a string to a f64 variable.
|
||||||
|
// IEEE 754 standard is used.
|
||||||
|
// Know limitation: limited to 18 significant digits
|
||||||
|
//
|
||||||
|
// The code is inspired by:
|
||||||
|
// Grzegorz Kraszewski krashan@teleinfo.pb.edu.pl
|
||||||
|
// URL: http://krashan.ppa.pl/articles/stringtofloat/
|
||||||
|
// Original license: MIT
|
||||||
|
// 96 bit operation utilities
|
||||||
|
//
|
||||||
|
// Note: when u128 will be available, these function can be refactored.
|
||||||
|
|
||||||
Copyright (c) 2019-2022 Dario Deledda. All rights reserved.
|
// f32 constants
|
||||||
Use of this source code is governed by an MIT license
|
pub const (
|
||||||
that can be found in the LICENSE file.
|
single_plus_zero = u32(0x0000_0000)
|
||||||
|
single_minus_zero = u32(0x8000_0000)
|
||||||
|
single_plus_infinity = u32(0x7F80_0000)
|
||||||
|
single_minus_infinity = u32(0xFF80_0000)
|
||||||
|
)
|
||||||
|
|
||||||
This file contains utilities for convert a string in a f64 variable
|
// f64 constants
|
||||||
IEEE 754 standard is used
|
pub const (
|
||||||
|
digits = 18
|
||||||
|
double_plus_zero = u64(0x0000000000000000)
|
||||||
|
double_minus_zero = u64(0x8000000000000000)
|
||||||
|
double_plus_infinity = u64(0x7FF0000000000000)
|
||||||
|
double_minus_infinity = u64(0xFFF0000000000000)
|
||||||
|
)
|
||||||
|
|
||||||
Know limitation:
|
// char constants
|
||||||
- limited to 18 significant digits
|
pub const (
|
||||||
|
c_dpoint = `.`
|
||||||
The code is inspired by:
|
c_plus = `+`
|
||||||
Grzegorz Kraszewski krashan@teleinfo.pb.edu.pl
|
c_minus = `-`
|
||||||
URL: http://krashan.ppa.pl/articles/stringtofloat/
|
c_zero = `0`
|
||||||
Original license: MIT
|
c_nine = `9`
|
||||||
|
c_ten = u32(10)
|
||||||
96 bit operation utilities
|
)
|
||||||
Note: when u128 will be available these function can be refactored
|
|
||||||
*/
|
|
||||||
|
|
||||||
// right logical shift 96 bit
|
// right logical shift 96 bit
|
||||||
fn lsr96(s2 u32, s1 u32, s0 u32) (u32, u32, u32) {
|
fn lsr96(s2 u32, s1 u32, s0 u32) (u32, u32, u32) {
|
||||||
|
|
@ -78,48 +99,7 @@ fn sub96(s2 u32, s1 u32, s0 u32, d2 u32, d1 u32, d0 u32) (u32, u32, u32) {
|
||||||
return r2, r1, r0
|
return r2, r1, r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants
|
|
||||||
|
|
||||||
pub const (
|
|
||||||
//
|
|
||||||
// f32 constants
|
|
||||||
//
|
|
||||||
single_plus_zero = u32(0x0000_0000)
|
|
||||||
single_minus_zero = u32(0x8000_0000)
|
|
||||||
single_plus_infinity = u32(0x7F80_0000)
|
|
||||||
single_minus_infinity = u32(0xFF80_0000)
|
|
||||||
//
|
|
||||||
// f64 constants
|
|
||||||
//
|
|
||||||
digits = 18
|
|
||||||
double_plus_zero = u64(0x0000000000000000)
|
|
||||||
double_minus_zero = u64(0x8000000000000000)
|
|
||||||
double_plus_infinity = u64(0x7FF0000000000000)
|
|
||||||
double_minus_infinity = u64(0xFFF0000000000000)
|
|
||||||
//
|
|
||||||
// Possible parser return values.
|
|
||||||
//
|
|
||||||
parser_ok = 0 // parser finished OK
|
|
||||||
parser_pzero = 1 // no digits or number is smaller than +-2^-1022
|
|
||||||
parser_mzero = 2 // number is negative, module smaller
|
|
||||||
parser_pinf = 3 // number is higher than +HUGE_VAL
|
|
||||||
parser_minf = 4 // number is lower than -HUGE_VAL
|
|
||||||
parser_invalid_number = 5 // invalid number, used for '#@%^' for example
|
|
||||||
//
|
|
||||||
// char constants
|
|
||||||
// Note: Modify these if working with non-ASCII encoding
|
|
||||||
//
|
|
||||||
c_dpoint = `.`
|
|
||||||
c_plus = `+`
|
|
||||||
c_minus = `-`
|
|
||||||
c_zero = `0`
|
|
||||||
c_nine = `9`
|
|
||||||
c_ten = u32(10)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
|
|
||||||
// NOTE: Modify these if working with non-ASCII encoding
|
|
||||||
fn is_digit(x byte) bool {
|
fn is_digit(x byte) bool {
|
||||||
return (x >= strconv.c_zero && x <= strconv.c_nine) == true
|
return (x >= strconv.c_zero && x <= strconv.c_nine) == true
|
||||||
}
|
}
|
||||||
|
|
@ -132,14 +112,21 @@ fn is_exp(x byte) bool {
|
||||||
return (x == `E` || x == `e`) == true
|
return (x == `E` || x == `e`) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Possible parser return values.
|
||||||
String parser
|
enum ParserState {
|
||||||
NOTE: #TOFIX need one char after the last char of the number
|
ok // parser finished OK
|
||||||
*/
|
pzero // no digits or number is smaller than +-2^-1022
|
||||||
|
mzero // number is negative, module smaller
|
||||||
|
pinf // number is higher than +HUGE_VAL
|
||||||
|
minf // number is lower than -HUGE_VAL
|
||||||
|
invalid_number // invalid number, used for '#@%^' for example
|
||||||
|
}
|
||||||
|
|
||||||
fn parser(s string) (int, PrepNumber) {
|
// parser tries to parse the given string into a number
|
||||||
|
// NOTE: #TOFIX need one char after the last char of the number
|
||||||
|
fn parser(s string) (ParserState, PrepNumber) {
|
||||||
mut digx := 0
|
mut digx := 0
|
||||||
mut result := strconv.parser_ok
|
mut result := ParserState.ok
|
||||||
mut expneg := false
|
mut expneg := false
|
||||||
mut expexp := 0
|
mut expexp := 0
|
||||||
mut i := 0
|
mut i := 0
|
||||||
|
|
@ -216,45 +203,45 @@ fn parser(s string) (int, PrepNumber) {
|
||||||
pn.exponent += expexp
|
pn.exponent += expexp
|
||||||
if pn.mantissa == 0 {
|
if pn.mantissa == 0 {
|
||||||
if pn.negative {
|
if pn.negative {
|
||||||
result = strconv.parser_mzero
|
result = .mzero
|
||||||
} else {
|
} else {
|
||||||
result = strconv.parser_pzero
|
result = .pzero
|
||||||
}
|
}
|
||||||
} else if pn.exponent > 309 {
|
} else if pn.exponent > 309 {
|
||||||
if pn.negative {
|
if pn.negative {
|
||||||
result = strconv.parser_minf
|
result = .minf
|
||||||
} else {
|
} else {
|
||||||
result = strconv.parser_pinf
|
result = .pinf
|
||||||
}
|
}
|
||||||
} else if pn.exponent < -328 {
|
} else if pn.exponent < -328 {
|
||||||
if pn.negative {
|
if pn.negative {
|
||||||
result = strconv.parser_mzero
|
result = .mzero
|
||||||
} else {
|
} else {
|
||||||
result = strconv.parser_pzero
|
result = .pzero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i == 0 && s.len > 0 {
|
if i == 0 && s.len > 0 {
|
||||||
return strconv.parser_invalid_number, pn
|
return ParserState.invalid_number, pn
|
||||||
}
|
}
|
||||||
return result, pn
|
return result, pn
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// converter returns a u64 with the bit image of the f64 number
|
||||||
Converter to the bit form of the f64 number
|
|
||||||
*/
|
|
||||||
|
|
||||||
// converter return a u64 with the bit image of the f64 number
|
|
||||||
fn converter(mut pn PrepNumber) u64 {
|
fn converter(mut pn PrepNumber) u64 {
|
||||||
mut binexp := 92
|
mut binexp := 92
|
||||||
mut s2 := u32(0) // 96-bit precision integer
|
// s0,s1,s2 are the parts of a 96-bit precision integer
|
||||||
|
mut s2 := u32(0)
|
||||||
mut s1 := u32(0)
|
mut s1 := u32(0)
|
||||||
mut s0 := u32(0)
|
mut s0 := u32(0)
|
||||||
mut q2 := u32(0) // 96-bit precision integer
|
// q0,q1,q2 are the parts of a 96-bit precision integer
|
||||||
|
mut q2 := u32(0)
|
||||||
mut q1 := u32(0)
|
mut q1 := u32(0)
|
||||||
mut q0 := u32(0)
|
mut q0 := u32(0)
|
||||||
mut r2 := u32(0) // 96-bit precision integer
|
// r0,r1,r2 are the parts of a 96-bit precision integer
|
||||||
|
mut r2 := u32(0)
|
||||||
mut r1 := u32(0)
|
mut r1 := u32(0)
|
||||||
mut r0 := u32(0)
|
mut r0 := u32(0)
|
||||||
|
//
|
||||||
mask28 := u32(u64(0xF) << 28)
|
mask28 := u32(u64(0xF) << 28)
|
||||||
mut result := u64(0)
|
mut result := u64(0)
|
||||||
// working on 3 u32 to have 96 bit precision
|
// working on 3 u32 to have 96 bit precision
|
||||||
|
|
@ -404,35 +391,30 @@ fn converter(mut pn PrepNumber) u64 {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// atof64 parses the string `s`, and if possible, converts it into a f64 number
|
||||||
|
|
||||||
// atof64 return a f64 from a string doing a parsing operation
|
|
||||||
pub fn atof64(s string) ?f64 {
|
pub fn atof64(s string) ?f64 {
|
||||||
if s.len == 0 {
|
if s.len == 0 {
|
||||||
return error('expected a number found an empty string')
|
return error('expected a number found an empty string')
|
||||||
}
|
}
|
||||||
mut pn := PrepNumber{}
|
|
||||||
mut res_parsing := 0
|
|
||||||
mut res := Float64u{}
|
mut res := Float64u{}
|
||||||
|
mut res_parsing, mut pn := parser(s)
|
||||||
res_parsing, pn = parser(s)
|
|
||||||
match res_parsing {
|
match res_parsing {
|
||||||
strconv.parser_ok {
|
.ok {
|
||||||
res.u = converter(mut pn)
|
res.u = converter(mut pn)
|
||||||
}
|
}
|
||||||
strconv.parser_pzero {
|
.pzero {
|
||||||
res.u = strconv.double_plus_zero
|
res.u = strconv.double_plus_zero
|
||||||
}
|
}
|
||||||
strconv.parser_mzero {
|
.mzero {
|
||||||
res.u = strconv.double_minus_zero
|
res.u = strconv.double_minus_zero
|
||||||
}
|
}
|
||||||
strconv.parser_pinf {
|
.pinf {
|
||||||
res.u = strconv.double_plus_infinity
|
res.u = strconv.double_plus_infinity
|
||||||
}
|
}
|
||||||
strconv.parser_minf {
|
.minf {
|
||||||
res.u = strconv.double_minus_infinity
|
res.u = strconv.double_minus_infinity
|
||||||
}
|
}
|
||||||
else {
|
.invalid_number {
|
||||||
return error('not a number')
|
return error('not a number')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,11 +142,11 @@ pub fn h_divider(divider string) string {
|
||||||
// ==== TITLE =========================
|
// ==== TITLE =========================
|
||||||
pub fn header_left(text string, divider string) string {
|
pub fn header_left(text string, divider string) string {
|
||||||
plain_text := strip_ansi(text)
|
plain_text := strip_ansi(text)
|
||||||
xcols, _ := get_terminal_size()
|
xcols, _ := get_terminal_size() // can get 0 in lldb/gdb
|
||||||
cols := imax(1, xcols)
|
cols := imax(1, xcols)
|
||||||
relement := if divider.len > 0 { divider } else { ' ' }
|
relement := if divider.len > 0 { divider } else { ' ' }
|
||||||
hstart := relement.repeat(4)[0..4]
|
hstart := relement.repeat(4)[0..4]
|
||||||
remaining_cols := (cols - (hstart.len + 1 + plain_text.len + 1))
|
remaining_cols := imax(0, (cols - (hstart.len + 1 + plain_text.len + 1)))
|
||||||
hend := relement.repeat((remaining_cols + 1) / relement.len)[0..remaining_cols]
|
hend := relement.repeat((remaining_cols + 1) / relement.len)[0..remaining_cols]
|
||||||
return '$hstart $text $hend'
|
return '$hstart $text $hend'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module scanner
|
module scanner
|
||||||
|
|
||||||
import math
|
|
||||||
import toml.input
|
import toml.input
|
||||||
import toml.token
|
import toml.token
|
||||||
import toml.util
|
import toml.util
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
digit_extras = [`_`, `.`, `x`, `o`, `b`, `e`, `E`]
|
digit_extras = [`_`, `.`, `x`, `o`, `b`, `e`, `E`]
|
||||||
end_of_text = math.max_u32
|
end_of_text = 4294967295
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scanner contains the necessary fields for the state of the scan process.
|
// Scanner contains the necessary fields for the state of the scan process.
|
||||||
|
|
@ -346,7 +345,7 @@ fn (mut s Scanner) new_token(kind token.Kind, lit string, len int) token.Token {
|
||||||
return token.Token{
|
return token.Token{
|
||||||
kind: kind
|
kind: kind
|
||||||
lit: lit
|
lit: lit
|
||||||
col: math.max(1, col)
|
col: if col < 1 { 1 } else { col }
|
||||||
line_nr: s.line_nr + 1
|
line_nr: s.line_nr + 1
|
||||||
pos: s.pos - s.header_len - len + 1
|
pos: s.pos - s.header_len - len + 1
|
||||||
len: len
|
len: len
|
||||||
|
|
|
||||||
|
|
@ -1175,6 +1175,13 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
|
||||||
} else if res in import_aliases {
|
} else if res in import_aliases {
|
||||||
res = import_aliases[res]
|
res = import_aliases[res]
|
||||||
} else {
|
} else {
|
||||||
|
// FIXME: clean this case and remove the following if
|
||||||
|
// because it is an hack to format well the type when
|
||||||
|
// there is a []modul.name
|
||||||
|
if res.contains('[]') {
|
||||||
|
idx := res.index('.') or { -1 }
|
||||||
|
return res[idx + 1..]
|
||||||
|
}
|
||||||
// types defined by the user
|
// types defined by the user
|
||||||
// mod.submod.submod2.Type => submod2.Type
|
// mod.submod.submod2.Type => submod2.Type
|
||||||
mut parts := res.split('.')
|
mut parts := res.split('.')
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ mut:
|
||||||
inside_println_arg bool
|
inside_println_arg bool
|
||||||
inside_decl_rhs bool
|
inside_decl_rhs bool
|
||||||
inside_if_guard bool // true inside the guard condition of `if x := opt() {}`
|
inside_if_guard bool // true inside the guard condition of `if x := opt() {}`
|
||||||
|
comptime_call_pos int // needed for correctly checking use before decl for templates
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &ast.Table, pref &pref.Preferences) &Checker {
|
pub fn new_checker(table &ast.Table, pref &pref.Preferences) &Checker {
|
||||||
|
|
@ -3127,9 +3128,16 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||||
return obj.typ
|
return obj.typ
|
||||||
}
|
}
|
||||||
ast.Var {
|
ast.Var {
|
||||||
// incase var was not marked as used yet (vweb tmpl)
|
// inside vweb tmpl ident positions are meaningless, use the position of the comptime call.
|
||||||
// obj.is_used = true
|
// if the variable is declared before the comptime call then we can assume all is well.
|
||||||
if node.pos.pos < obj.pos.pos {
|
// `node.name !in node.scope.objects && node.scope.start_pos < c.comptime_call_pos` (inherited)
|
||||||
|
node_pos := if c.pref.is_vweb && node.name !in node.scope.objects
|
||||||
|
&& node.scope.start_pos < c.comptime_call_pos {
|
||||||
|
c.comptime_call_pos
|
||||||
|
} else {
|
||||||
|
node.pos.pos
|
||||||
|
}
|
||||||
|
if node_pos < obj.pos.pos {
|
||||||
c.error('undefined variable `$node.name` (used before declaration)',
|
c.error('undefined variable `$node.name` (used before declaration)',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,28 +36,8 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
||||||
is_vweb: true
|
is_vweb: true
|
||||||
}
|
}
|
||||||
mut c2 := new_checker(c.table, pref2)
|
mut c2 := new_checker(c.table, pref2)
|
||||||
|
c2.comptime_call_pos = node.pos.pos
|
||||||
c2.check(node.vweb_tmpl)
|
c2.check(node.vweb_tmpl)
|
||||||
mut caller_scope := c.fn_scope.innermost(node.pos.pos)
|
|
||||||
mut i := 0 // tmp counter var for skipping first three tmpl vars
|
|
||||||
for k, _ in c2.file.scope.children[0].objects {
|
|
||||||
if i < 2 {
|
|
||||||
// Skip first three because they are tmpl vars see vlib/vweb/tmpl/tmpl.v
|
|
||||||
i++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tmpl_obj := unsafe { c2.file.scope.children[0].objects[k] }
|
|
||||||
if tmpl_obj is ast.Var {
|
|
||||||
if mut caller_var := caller_scope.find_var(tmpl_obj.name) {
|
|
||||||
// var is used in the tmpl so mark it as used in the caller
|
|
||||||
caller_var.is_used = true
|
|
||||||
// update props from the caller scope var to the tmpl scope var
|
|
||||||
c2.file.scope.children[0].objects[k] = ast.Var{
|
|
||||||
...(*caller_var)
|
|
||||||
pos: tmpl_obj.pos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.warnings << c2.warnings
|
c.warnings << c2.warnings
|
||||||
c.errors << c2.errors
|
c.errors << c2.errors
|
||||||
c.notices << c2.notices
|
c.notices << c2.notices
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,22 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
mut elem_type := ast.void_type
|
mut elem_type := ast.void_type
|
||||||
// []string - was set in parser
|
// []string - was set in parser
|
||||||
if node.typ != ast.void_type {
|
if node.typ != ast.void_type {
|
||||||
|
if node.elem_type != 0 {
|
||||||
|
elem_sym := c.table.sym(node.elem_type)
|
||||||
|
if elem_sym.kind == .struct_ {
|
||||||
|
elem_info := elem_sym.info as ast.Struct
|
||||||
|
if elem_info.generic_types.len > 0 && elem_info.concrete_types.len == 0
|
||||||
|
&& !node.elem_type.has_flag(.generic) {
|
||||||
|
if c.table.cur_concrete_types.len == 0 {
|
||||||
|
c.error('generic struct must specify type parameter, e.g. Foo<int>',
|
||||||
|
node.elem_type_pos)
|
||||||
|
} else {
|
||||||
|
c.error('generic struct must specify type parameter, e.g. Foo<T>',
|
||||||
|
node.elem_type_pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if node.exprs.len == 0 {
|
if node.exprs.len == 0 {
|
||||||
if node.has_cap {
|
if node.has_cap {
|
||||||
c.check_array_init_para_type('cap', node.cap_expr, node.pos)
|
c.check_array_init_para_type('cap', node.cap_expr, node.pos)
|
||||||
|
|
@ -244,6 +260,22 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||||
// `x := map[string]string` - set in parser
|
// `x := map[string]string` - set in parser
|
||||||
if node.typ != 0 {
|
if node.typ != 0 {
|
||||||
info := c.table.sym(node.typ).map_info()
|
info := c.table.sym(node.typ).map_info()
|
||||||
|
if info.value_type != 0 {
|
||||||
|
val_sym := c.table.sym(info.value_type)
|
||||||
|
if val_sym.kind == .struct_ {
|
||||||
|
val_info := val_sym.info as ast.Struct
|
||||||
|
if val_info.generic_types.len > 0 && val_info.concrete_types.len == 0
|
||||||
|
&& !info.value_type.has_flag(.generic) {
|
||||||
|
if c.table.cur_concrete_types.len == 0 {
|
||||||
|
c.error('generic struct `$val_sym.name` must specify type parameter, e.g. Foo<int>',
|
||||||
|
node.pos)
|
||||||
|
} else {
|
||||||
|
c.error('generic struct `$val_sym.name` must specify type parameter, e.g. Foo<T>',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
c.ensure_type_exists(info.key_type, node.pos) or {}
|
c.ensure_type_exists(info.key_type, node.pos) or {}
|
||||||
c.ensure_type_exists(info.value_type, node.pos) or {}
|
c.ensure_type_exists(info.value_type, node.pos) or {}
|
||||||
node.key_type = info.key_type
|
node.key_type = info.key_type
|
||||||
|
|
|
||||||
|
|
@ -1726,6 +1726,10 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
|
||||||
if is_map && arg_expr.return_type in [ast.void_type, 0] {
|
if is_map && arg_expr.return_type in [ast.void_type, 0] {
|
||||||
c.error('type mismatch, `$arg_expr.name` does not return anything', arg_expr.pos)
|
c.error('type mismatch, `$arg_expr.name` does not return anything', arg_expr.pos)
|
||||||
} else if !is_map && arg_expr.return_type != ast.bool_type {
|
} else if !is_map && arg_expr.return_type != ast.bool_type {
|
||||||
|
if arg_expr.or_block.kind != .absent && arg_expr.return_type.has_flag(.optional)
|
||||||
|
&& arg_expr.return_type.clear_flag(.optional) == ast.bool_type {
|
||||||
|
return
|
||||||
|
}
|
||||||
c.error('type mismatch, `$arg_expr.name` must return a bool', arg_expr.pos)
|
c.error('type mismatch, `$arg_expr.name` must return a bool', arg_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/array_of_generic_struct_init_err.vv:6:15: error: generic struct must specify type parameter, e.g. Foo<int>
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | mut arr := []Item{}
|
||||||
|
| ~~~~
|
||||||
|
7 | }
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
struct Item<T>{
|
||||||
|
val T
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut arr := []Item{}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
vlib/v/checker/tests/check_err_msg_with_generics.vv:15:10: error: cannot cast struct `BSTree<Result<[]Token, Err<string>>>` to `int`
|
||||||
|
13 | fn test_err_msg() {
|
||||||
|
14 | typ := datatypes.BSTree<Result<[]Token, Err<string>>>{}
|
||||||
|
15 | println(int(typ))
|
||||||
|
| ~~~~~~~~
|
||||||
|
16 | }
|
||||||
|
vlib/datatypes/bstree.v:190:17: error: cannot append `T` to `[]T`
|
||||||
|
188 | }
|
||||||
|
189 | bst.in_order_traversal_helper(node.left, mut result)
|
||||||
|
190 | result << node.value
|
||||||
|
| ~~~~~
|
||||||
|
191 | bst.in_order_traversal_helper(node.right, mut result)
|
||||||
|
192 | }
|
||||||
|
vlib/datatypes/bstree.v:210:17: error: cannot append `T` to `[]T`
|
||||||
|
208 | bst.post_order_traversal_helper(node.left, mut result)
|
||||||
|
209 | bst.post_order_traversal_helper(node.right, mut result)
|
||||||
|
210 | result << node.value
|
||||||
|
| ~~~~~
|
||||||
|
211 | }
|
||||||
|
212 |
|
||||||
|
vlib/datatypes/bstree.v:226:17: error: cannot append `T` to `[]T`
|
||||||
|
224 | return
|
||||||
|
225 | }
|
||||||
|
226 | result << node.value
|
||||||
|
| ~~~~~
|
||||||
|
227 | bst.pre_order_traversal_helper(node.left, mut result)
|
||||||
|
228 | bst.pre_order_traversal_helper(node.right, mut result)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import datatypes
|
||||||
|
|
||||||
|
type Result<T, U> = Err<U> | Ok<T>
|
||||||
|
|
||||||
|
struct Ok<T> {
|
||||||
|
value T
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Err<U> {
|
||||||
|
value U
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_err_msg() {
|
||||||
|
typ := datatypes.BSTree<Result<[]Token, Err<string>>>{}
|
||||||
|
println(int(typ))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/map_of_generic_struct_init_err.vv:6:11: error: generic struct `Item` must specify type parameter, e.g. Foo<int>
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | mut m := map[string]Item{}
|
||||||
|
| ~~~~~~~~~~~~~~~~~
|
||||||
|
7 | }
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
struct Item<T>{
|
||||||
|
val T
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut m := map[string]Item{}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
vlib/v/checker/tests/struct_field_name_err.vv:2:2: error: field name `Architecture` cannot contain uppercase letters, use snake_case instead
|
||||||
|
1 | struct Release {
|
||||||
|
2 | Architecture []string
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
3 | Components []string
|
||||||
|
4 | }
|
||||||
|
vlib/v/checker/tests/struct_field_name_err.vv:3:2: error: field name `Components` cannot contain uppercase letters, use snake_case instead
|
||||||
|
1 | struct Release {
|
||||||
|
2 | Architecture []string
|
||||||
|
3 | Components []string
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
4 | }
|
||||||
|
5 |
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
struct Release {
|
||||||
|
Architecture []string
|
||||||
|
Components []string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
r := Release{}
|
||||||
|
println(r)
|
||||||
|
}
|
||||||
|
|
@ -673,7 +673,11 @@ fn (mut g Gen) gen_array_contains_methods() {
|
||||||
fn_name := '${left_type_str}_contains'
|
fn_name := '${left_type_str}_contains'
|
||||||
left_info := left_final_sym.info as ast.Array
|
left_info := left_final_sym.info as ast.Array
|
||||||
mut elem_type_str := g.typ(left_info.elem_type)
|
mut elem_type_str := g.typ(left_info.elem_type)
|
||||||
elem_sym := g.table.sym(left_info.elem_type)
|
mut elem_sym := g.table.sym(left_info.elem_type)
|
||||||
|
if elem_sym.kind == .alias {
|
||||||
|
info := elem_sym.info as ast.Alias
|
||||||
|
elem_sym = g.table.sym(info.parent_type)
|
||||||
|
}
|
||||||
if elem_sym.kind == .function {
|
if elem_sym.kind == .function {
|
||||||
left_type_str = 'Array_voidptr'
|
left_type_str = 'Array_voidptr'
|
||||||
elem_type_str = 'voidptr'
|
elem_type_str = 'voidptr'
|
||||||
|
|
@ -751,7 +755,11 @@ fn (mut g Gen) gen_array_index_methods() {
|
||||||
fn_name := '${left_type_str}_index'
|
fn_name := '${left_type_str}_index'
|
||||||
info := final_left_sym.info as ast.Array
|
info := final_left_sym.info as ast.Array
|
||||||
mut elem_type_str := g.typ(info.elem_type)
|
mut elem_type_str := g.typ(info.elem_type)
|
||||||
elem_sym := g.table.sym(info.elem_type)
|
mut elem_sym := g.table.sym(info.elem_type)
|
||||||
|
if elem_sym.kind == .alias {
|
||||||
|
info_t := elem_sym.info as ast.Alias
|
||||||
|
elem_sym = g.table.sym(info_t.parent_type)
|
||||||
|
}
|
||||||
if elem_sym.kind == .function {
|
if elem_sym.kind == .function {
|
||||||
left_type_str = 'Array_voidptr'
|
left_type_str = 'Array_voidptr'
|
||||||
elem_type_str = 'voidptr'
|
elem_type_str = 'voidptr'
|
||||||
|
|
|
||||||
|
|
@ -238,11 +238,12 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
||||||
} else {
|
} else {
|
||||||
g.out.go_back_to(pos)
|
g.out.go_back_to(pos)
|
||||||
is_var_mut := !is_decl && left.is_auto_deref_var()
|
is_var_mut := !is_decl && left.is_auto_deref_var()
|
||||||
addr := if is_var_mut { '' } else { '&' }
|
addr_left := if is_var_mut { '' } else { '&' }
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.write('memcpy($addr')
|
g.write('memcpy($addr_left')
|
||||||
g.expr(left)
|
g.expr(left)
|
||||||
g.writeln(', &$v_var, sizeof($arr_typ));')
|
addr_val := if is_fixed_array_var { '' } else { '&' }
|
||||||
|
g.writeln(', $addr_val$v_var, sizeof($arr_typ));')
|
||||||
}
|
}
|
||||||
g.is_assign_lhs = false
|
g.is_assign_lhs = false
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -972,7 +972,7 @@ fn (g Gen) optional_type_text(styp string, base string) string {
|
||||||
ret := 'struct $styp {
|
ret := 'struct $styp {
|
||||||
byte state;
|
byte state;
|
||||||
IError err;
|
IError err;
|
||||||
byte data[sizeof($size)];
|
byte data[sizeof($size) > 0 ? sizeof($size) : 1];
|
||||||
}'
|
}'
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
@ -2645,12 +2645,13 @@ fn (mut g Gen) autofree_variable(v ast.Var) {
|
||||||
g.autofree_var_call('string_free', v)
|
g.autofree_var_call('string_free', v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sym.has_method('free') {
|
if g.pref.experimental && v.typ.is_ptr() && sym.name.after('.')[0].is_capital() {
|
||||||
g.autofree_var_call(free_fn, v)
|
|
||||||
} else if g.pref.experimental && v.typ.is_ptr() && sym.name.after('.')[0].is_capital() {
|
|
||||||
// Free user reference types
|
// Free user reference types
|
||||||
g.autofree_var_call('free', v)
|
g.autofree_var_call('free', v)
|
||||||
}
|
}
|
||||||
|
if sym.has_method('free') {
|
||||||
|
g.autofree_var_call(free_fn, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
|
fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
|
||||||
|
|
@ -2698,8 +2699,12 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
|
||||||
if v.typ == ast.error_type && !v.is_autofree_tmp {
|
if v.typ == ast.error_type && !v.is_autofree_tmp {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if v.is_auto_heap {
|
||||||
|
af.writeln('\t${free_fn_name}(${c_name(v.name)}); // autofreed heap var $g.cur_mod.name $g.is_builtin_mod')
|
||||||
|
} else {
|
||||||
af.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var $g.cur_mod.name $g.is_builtin_mod')
|
af.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var $g.cur_mod.name $g.is_builtin_mod')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
g.autofree_scope_stmts << af.str()
|
g.autofree_scope_stmts << af.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3697,10 +3702,8 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||||
g.write('${name}.val')
|
g.write('${name}.val')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: investigate why node.obj is pointing to outdated ScopeObject?
|
v := node.obj
|
||||||
// v := node.obj
|
if v is ast.Var {
|
||||||
// if v is ast.Var {
|
|
||||||
if v := node.scope.find_var(node.name) {
|
|
||||||
is_auto_heap = v.is_auto_heap && (!g.is_assign_lhs || g.assign_op != .decl_assign)
|
is_auto_heap = v.is_auto_heap && (!g.is_assign_lhs || g.assign_op != .decl_assign)
|
||||||
if is_auto_heap {
|
if is_auto_heap {
|
||||||
g.write('(*(')
|
g.write('(*(')
|
||||||
|
|
|
||||||
|
|
@ -1206,6 +1206,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
// `json__encode` => `json__encode_User`
|
// `json__encode` => `json__encode_User`
|
||||||
// encode_name := c_name(name) + '_' + util.no_dots(json_type_str)
|
// encode_name := c_name(name) + '_' + util.no_dots(json_type_str)
|
||||||
encode_name := js_enc_name(json_type_str)
|
encode_name := js_enc_name(json_type_str)
|
||||||
|
g.empty_line = true
|
||||||
g.writeln('// json.encode')
|
g.writeln('// json.encode')
|
||||||
g.write('cJSON* $json_obj = ${encode_name}(')
|
g.write('cJSON* $json_obj = ${encode_name}(')
|
||||||
if node.args[0].typ.is_ptr() {
|
if node.args[0].typ.is_ptr() {
|
||||||
|
|
@ -1225,6 +1226,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
typ := c_name(g.typ(ast_type.typ))
|
typ := c_name(g.typ(ast_type.typ))
|
||||||
fn_name := c_name(name) + '_' + typ
|
fn_name := c_name(name) + '_' + typ
|
||||||
g.gen_json_for_type(ast_type.typ)
|
g.gen_json_for_type(ast_type.typ)
|
||||||
|
g.empty_line = true
|
||||||
g.writeln('// json.decode')
|
g.writeln('// json.decode')
|
||||||
g.write('cJSON* $json_obj = json__json_parse(')
|
g.write('cJSON* $json_obj = json__json_parse(')
|
||||||
// Skip the first argument in json.decode which is a type
|
// Skip the first argument in json.decode which is a type
|
||||||
|
|
@ -1233,10 +1235,10 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
g.call_args(node)
|
g.call_args(node)
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
tmp2 = g.new_tmp_var()
|
tmp2 = g.new_tmp_var()
|
||||||
g.writeln('Option_$typ $tmp2 = $fn_name ($json_obj);')
|
g.writeln('Option_$typ $tmp2 = ${fn_name}($json_obj);')
|
||||||
}
|
}
|
||||||
if !g.is_autofree {
|
if !g.is_autofree {
|
||||||
g.write('cJSON_Delete($json_obj); //del')
|
g.write('cJSON_Delete($json_obj); // del')
|
||||||
}
|
}
|
||||||
g.write('\n$cur_line')
|
g.write('\n$cur_line')
|
||||||
name = ''
|
name = ''
|
||||||
|
|
|
||||||
|
|
@ -626,7 +626,8 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||||
if elem_sym.kind == .function {
|
if elem_sym.kind == .function {
|
||||||
g.write(', _MOV((voidptr[]){ ')
|
g.write(', _MOV((voidptr[]){ ')
|
||||||
} else if elem_is_array_var {
|
} else if elem_is_array_var {
|
||||||
g.write(', &')
|
addr := if elem_sym.kind == .array_fixed { '' } else { '&' }
|
||||||
|
g.write(', $addr')
|
||||||
} else {
|
} else {
|
||||||
g.write(', _MOV(($elem_type_str[]){ ')
|
g.write(', _MOV(($elem_type_str[]){ ')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -245,10 +245,6 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
||||||
println('$path:${i + 1}: $line')
|
println('$path:${i + 1}: $line')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut scope := &ast.Scope{
|
|
||||||
start_pos: 0
|
|
||||||
parent: p.table.global_scope
|
|
||||||
}
|
|
||||||
$if trace_comptime ? {
|
$if trace_comptime ? {
|
||||||
println('')
|
println('')
|
||||||
println('>>> template for $path:')
|
println('>>> template for $path:')
|
||||||
|
|
@ -256,25 +252,11 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
||||||
println('>>> end of template END')
|
println('>>> end of template END')
|
||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
mut file := parse_comptime(v_code, p.table, p.pref, scope)
|
// the tmpl inherits all parent scopes. previous functionality was just to
|
||||||
|
// inherit the scope from which the comptime call was made and no parents.
|
||||||
|
// this is much simpler and allws access to globals. can be changed if needed.
|
||||||
|
mut file := parse_comptime(tmpl_path, v_code, p.table, p.pref, p.scope)
|
||||||
file.path = tmpl_path
|
file.path = tmpl_path
|
||||||
// copy vars from current fn scope into vweb_tmpl scope
|
|
||||||
for mut stmt in file.stmts {
|
|
||||||
if mut stmt is ast.FnDecl {
|
|
||||||
if stmt.name == 'main.vweb_tmpl_$tmp_fn_name' {
|
|
||||||
for _, mut obj in p.scope.objects {
|
|
||||||
if mut obj is ast.Var {
|
|
||||||
stmt.scope.register(ast.Var{
|
|
||||||
...obj
|
|
||||||
is_used: true
|
|
||||||
pos: stmt.body_pos
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ast.ComptimeCall{
|
return ast.ComptimeCall{
|
||||||
scope: 0
|
scope: 0
|
||||||
is_vweb: true
|
is_vweb: true
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,12 @@ pub fn parse_stmt(text string, table &ast.Table, scope &ast.Scope) ast.Stmt {
|
||||||
return p.stmt(false)
|
return p.stmt(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_comptime(text string, table &ast.Table, pref &pref.Preferences, scope &ast.Scope) &ast.File {
|
pub fn parse_comptime(tmpl_path string, text string, table &ast.Table, pref &pref.Preferences, scope &ast.Scope) &ast.File {
|
||||||
$if trace_parse_comptime ? {
|
$if trace_parse_comptime ? {
|
||||||
eprintln('> ${@MOD}.${@FN} text: $text')
|
eprintln('> ${@MOD}.${@FN} text: $text')
|
||||||
}
|
}
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
|
file_name: tmpl_path
|
||||||
scanner: scanner.new_scanner(text, .skip_comments, pref)
|
scanner: scanner.new_scanner(text, .skip_comments, pref)
|
||||||
table: table
|
table: table
|
||||||
pref: pref
|
pref: pref
|
||||||
|
|
@ -2139,10 +2140,12 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
p.expr_mod = ''
|
p.expr_mod = ''
|
||||||
// `map[string]int` initialization
|
// `map[string]int` initialization
|
||||||
if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr {
|
if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr {
|
||||||
|
mut pos := p.tok.pos()
|
||||||
map_type := p.parse_map_type()
|
map_type := p.parse_map_type()
|
||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind == .rcbr {
|
if p.tok.kind == .rcbr {
|
||||||
|
pos = pos.extend(p.tok.pos())
|
||||||
p.next()
|
p.next()
|
||||||
} else {
|
} else {
|
||||||
if p.pref.is_fmt {
|
if p.pref.is_fmt {
|
||||||
|
|
@ -2155,7 +2158,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
}
|
}
|
||||||
return ast.MapInit{
|
return ast.MapInit{
|
||||||
typ: map_type
|
typ: map_type
|
||||||
pos: p.prev_tok.pos()
|
pos: pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `chan typ{...}`
|
// `chan typ{...}`
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||||
p.next()
|
p.next()
|
||||||
is_field_volatile = true
|
is_field_volatile = true
|
||||||
}
|
}
|
||||||
is_embed := ((p.tok.lit.len > 1 && p.tok.lit[0].is_capital())
|
is_embed := ((p.tok.lit.len > 1 && p.tok.lit[0].is_capital()
|
||||||
|
&& (p.peek_tok.kind != .lsbr || p.peek_token(2).kind != .rsbr))
|
||||||
|| p.peek_tok.kind == .dot) && language == .v && p.peek_tok.kind != .key_fn
|
|| p.peek_tok.kind == .dot) && language == .v && p.peek_tok.kind != .key_fn
|
||||||
is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_global)
|
is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_global)
|
||||||
mut field_name := ''
|
mut field_name := ''
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,7 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||||
eprintln('Use `v $arg` instead.')
|
eprintln('Use `v $arg` instead.')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
if arg[0] == `-` {
|
if arg.len != 0 && arg[0] == `-` {
|
||||||
if arg[1..] in pref.list_of_flags_with_param {
|
if arg[1..] in pref.list_of_flags_with_param {
|
||||||
// skip parameter
|
// skip parameter
|
||||||
i++
|
i++
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
module pref
|
||||||
|
|
||||||
|
fn test_check_parametes() {
|
||||||
|
// reproducing issue https://github.com/vlang/v/issues/13983
|
||||||
|
_, cmd := parse_args_and_show_errors(['help'], [''], true)
|
||||||
|
// no command found from args
|
||||||
|
assert cmd == ''
|
||||||
|
}
|
||||||
|
|
@ -30,3 +30,12 @@ fn test_array_eval_count() {
|
||||||
a4 = Counter{}
|
a4 = Counter{}
|
||||||
assert a4.new_arr('all() failed').all(it == 2) == false
|
assert a4.new_arr('all() failed').all(it == 2) == false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opt_bool_fn() ?bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_called_with_opt_bool_fn() ? {
|
||||||
|
_ := [1, 2, 3].any(opt_bool_fn() ?)
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
$a.name
|
||||||
|
$b
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
[heap]
|
||||||
|
struct MyHeapStruct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure dereferencing of heap stucts works in selector expr (in tmpl),
|
||||||
|
fn test_heap_struct_dereferencing_in_selector_expr() {
|
||||||
|
a := MyHeapStruct{
|
||||||
|
name: 'my_heap_struct_a'
|
||||||
|
}
|
||||||
|
b := 2
|
||||||
|
$tmpl('comptime_call_tmpl_variable_scope_test.tpl')
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
struct Test1 {
|
||||||
|
mut:
|
||||||
|
value [4]int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t Test1) set(new_value [4]int) {
|
||||||
|
t.value = new_value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_fn_with_fixed_array_argument_1() {
|
||||||
|
mut t := Test1{}
|
||||||
|
|
||||||
|
println(t)
|
||||||
|
assert '$t.value' == '[0, 0, 0, 0]'
|
||||||
|
|
||||||
|
t.set([1, 2, 3, 4]!)
|
||||||
|
|
||||||
|
println(t)
|
||||||
|
assert '$t.value' == '[1, 2, 3, 4]'
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test2 {
|
||||||
|
mut:
|
||||||
|
fixed_value [2][4]int
|
||||||
|
dynamic_value [][4]int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t Test2) set(index int, new_value [4]int) {
|
||||||
|
t.fixed_value[index] = new_value
|
||||||
|
t.dynamic_value << new_value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_fn_with_fixed_array_argument_2() {
|
||||||
|
mut t := Test2{}
|
||||||
|
|
||||||
|
println(t)
|
||||||
|
assert '$t.fixed_value' == '[[0, 0, 0, 0], [0, 0, 0, 0]]'
|
||||||
|
assert '$t.dynamic_value' == '[]'
|
||||||
|
|
||||||
|
t.set(0, [1, 2, 3, 4]!)
|
||||||
|
println(t)
|
||||||
|
assert '$t.fixed_value' == '[[1, 2, 3, 4], [0, 0, 0, 0]]'
|
||||||
|
assert '$t.dynamic_value' == '[[1, 2, 3, 4]]'
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,6 @@ fn create(x int) &Foo {
|
||||||
fn (f &Foo) free() {
|
fn (f &Foo) free() {
|
||||||
println('> freeing Foo $f.x at address: ${voidptr(f)} | frees.len: $frees.len')
|
println('> freeing Foo $f.x at address: ${voidptr(f)} | frees.len: $frees.len')
|
||||||
frees << f.x
|
frees << f.x
|
||||||
// TODO: this should NOT be necessary - the compiler should do it automatically in the parent scope
|
|
||||||
unsafe { free(f) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_some_foos() {
|
fn create_some_foos() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue