mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
Compare commits
57 Commits
d53d95991d
...
428fd7f57f
Author | SHA1 | Date | |
---|---|---|---|
|
428fd7f57f | ||
|
453137384e | ||
|
6a4bfef2c5 | ||
|
9f5e9ba1cf | ||
|
ef5c3cdb73 | ||
|
5ec7ee916a | ||
|
b556f1302f | ||
|
fe9bdd4168 | ||
|
8ee1667a9a | ||
|
1d9835f0e4 | ||
|
6b978a6b5a | ||
|
43800a05e8 | ||
|
ecca3b155e | ||
|
600f891d3a | ||
|
b6d6d4b037 | ||
|
ecf8fcd45a | ||
|
177bb30013 | ||
|
367e38d7d1 | ||
|
def0161281 | ||
|
a1aca4c578 | ||
|
5061aeee64 | ||
|
f4c2ecfaa9 | ||
|
9be80198fc | ||
|
a609d6c9d1 | ||
|
fd81bae361 | ||
|
8861538c66 | ||
|
0f861db9b0 | ||
|
9750061d70 | ||
|
81e99a2af3 | ||
|
367289a1f1 | ||
|
2cd5b8a86d | ||
|
618961fab5 | ||
|
d97423d385 | ||
|
30d4e25385 | ||
|
32114a679a | ||
|
37e7d5f5ae | ||
|
8735694d13 | ||
|
77049600e6 | ||
|
b622dca915 | ||
|
e78e468d5f | ||
|
1c2b4e76dc | ||
|
112a1278bb | ||
|
8586f18383 | ||
|
a61a2fd328 | ||
|
c4a679186f | ||
|
490a014bf6 | ||
|
4ed9703e22 | ||
|
c881e7284d | ||
|
2f2dde8ad0 | ||
|
2fa177e310 | ||
|
2266ccecf3 | ||
|
b25288338c | ||
|
e0aba77cc5 | ||
|
c7f708e64d | ||
|
aa3d560b05 | ||
|
76e3b7dff8 | ||
|
fe87d20f20 |
@ -6,7 +6,7 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.v]
|
||||
[*.{v,js,css}]
|
||||
indent_style = tab
|
||||
|
||||
[*.{bat,cmd}]
|
||||
|
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -1,7 +1,6 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug
|
||||
title: (bug report summary)
|
||||
labels: Bug
|
||||
labels: [Bug]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
|
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@ -1,7 +1,6 @@
|
||||
name: 🚀 Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: (feature request summary)
|
||||
labels: Feature Request
|
||||
labels: [Feature Request]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
|
2
.github/workflows/c2v_ci.yml
vendored
2
.github/workflows/c2v_ci.yml
vendored
@ -60,7 +60,7 @@ jobs:
|
||||
doom-regressions:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
VFLAGS: -cc tcc
|
||||
DISPLAY: :99
|
||||
|
2
.github/workflows/gg_regressions_ci.yml
vendored
2
.github/workflows/gg_regressions_ci.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
gg-regressions:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
VFLAGS: -cc tcc
|
||||
DISPLAY: :99
|
||||
|
19
.github/workflows/module_docs_lint.yml
vendored
Normal file
19
.github/workflows/module_docs_lint.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Code CI vlib modules
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**/cmd/tools/vdoc/theme/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**/cmd/tools/vdoc/theme/**'
|
||||
|
||||
jobs:
|
||||
lint-module-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check Formatting
|
||||
uses: actionsx/prettier@v2
|
||||
with:
|
||||
args: --check cmd/tools/vdoc/theme
|
2
.github/workflows/other_ci.yml
vendored
2
.github/workflows/other_ci.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
||||
- name: Repeat -o hw.c examples/hello_world.v
|
||||
run: cmd/tools/repeat --max_time 251 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o hw.c examples/hello_world.v' . ./vmaster
|
||||
- name: Repeat -o v.c cmd/v
|
||||
run: cmd/tools/repeat --max_time 1701 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o v.c cmd/v' . ./vmaster
|
||||
run: cmd/tools/repeat --max_time 1731 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o v.c cmd/v' . ./vmaster
|
||||
|
||||
misc-tooling:
|
||||
runs-on: ubuntu-20.04
|
||||
|
2
.github/workflows/vab_ci.yml
vendored
2
.github/workflows/vab_ci.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
||||
v-compiles-os-android:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build V
|
||||
|
31
README.md
31
README.md
@ -201,34 +201,23 @@ cd v
|
||||
make
|
||||
```
|
||||
|
||||
## Installing editor/IDE plugin
|
||||
## Editor/IDE Plugins
|
||||
|
||||
V has plugins for many editors:
|
||||
To bring IDE functions for the V programming languages to your editor, check out
|
||||
[v-analyzer](https://github.com/v-analyzer/v-analyzer). It provides a
|
||||
[VS Code extension](https://marketplace.visualstudio.com/items?itemName=VOSCA.vscode-v-analyzer)
|
||||
and language server capabilities for other editors.
|
||||
|
||||
The plugin for JetBrains IDEs (IntelliJ, CLion, GoLand, etc.) also offers a great development
|
||||
experience with V. You can find all features in [its documentation](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html).
|
||||
|
||||
Other Plugins:
|
||||
|
||||
- [VS Code plugin](https://github.com/vlang/vscode-vlang)
|
||||
- [JetBrains IDE plugin](https://plugins.jetbrains.com/plugin/20287-vlang/docs/quick-start-guide.html)
|
||||
- [Vim plugins](https://github.com/vlang/awesome-v#vim)
|
||||
- [Emacs plugins](https://github.com/vlang/awesome-v#emacs)
|
||||
- [Sublime Text 3 plugins](https://github.com/vlang/awesome-v#sublime-text-3)
|
||||
- [Atom plugins](https://github.com/vlang/awesome-v#atom)
|
||||
|
||||
### IntelliSense
|
||||
|
||||
V has a Language Server:
|
||||
[VLS](https://github.com/vlang/vls).
|
||||
The VS Code plugin provides built-in support for VLS.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> VLS may be unstable at the moment.
|
||||
> If you encounter any problem, please create a new
|
||||
> [issue](https://github.com/vlang/vls/issues).
|
||||
|
||||
The plugin for JetBrains IDE (IntelliJ, CLion, GoLand, etc) at the moment is
|
||||
the best choice if you want a great V development experience.
|
||||
You can see all its features in
|
||||
[its documentation](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html).
|
||||
|
||||
## Testing and running the examples
|
||||
|
||||
Make sure V can compile itself:
|
||||
|
@ -12,7 +12,7 @@ import term
|
||||
|
||||
const (
|
||||
base_os = 'linux'
|
||||
os_names = ['linux', 'macos', 'windows']
|
||||
os_names = ['linux', 'macos', 'windows', 'freebsd', 'openbsd', 'solaris', 'termux']
|
||||
skip_modules = [
|
||||
'builtin.bare',
|
||||
'builtin.linux_bare.old',
|
||||
@ -103,7 +103,7 @@ fn (app App) gen_api_for_module_in_os(mod_name string, os_name string) string {
|
||||
for s in f.stmts {
|
||||
if s is ast.FnDecl {
|
||||
if s.is_pub {
|
||||
fn_signature := s.stringify_fn_decl(b.table, mod_name, map[string]string{})
|
||||
fn_signature := b.table.stringify_fn_decl(&s, mod_name, map[string]string{})
|
||||
fn_mod := s.modname()
|
||||
if fn_mod == mod_name {
|
||||
fline := '${fn_mod}: ${fn_signature}'
|
||||
|
@ -10,6 +10,7 @@ import v.ast
|
||||
import v.token
|
||||
import v.doc
|
||||
import v.pref
|
||||
import v.util { tabs }
|
||||
|
||||
const (
|
||||
css_js_assets = ['doc.css', 'normalize.css', 'doc.js', 'dark-mode.js']
|
||||
@ -249,27 +250,27 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
||||
version).replace('{{ light_icon }}', vd.assets['light_icon']).replace('{{ dark_icon }}',
|
||||
vd.assets['dark_icon']).replace('{{ menu_icon }}', vd.assets['menu_icon']).replace('{{ head_assets }}',
|
||||
if cfg.inline_assets {
|
||||
'\n${tabs[0]}<style>' + vd.assets['doc_css'] + '</style>\n${tabs[0]}<style>' +
|
||||
vd.assets['normalize_css'] + '</style>\n${tabs[0]}<script>' +
|
||||
vd.assets['dark_mode_js'] + '</script>'
|
||||
'<style>${vd.assets['doc_css']}</style>
|
||||
${tabs(2)}<style>${vd.assets['normalize_css']}</style>
|
||||
${tabs(2)}<script>${vd.assets['dark_mode_js']}</script>'
|
||||
} else {
|
||||
'\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['doc_css'] +
|
||||
'" />\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['normalize_css'] +
|
||||
'" />\n${tabs[0]}<script src="' + vd.assets['dark_mode_js'] + '"></script>'
|
||||
'<link rel="stylesheet" href="${vd.assets['doc_css']}" />
|
||||
${tabs(2)}<link rel="stylesheet" href="${vd.assets['normalize_css']}" />
|
||||
${tabs(2)}<script src="${vd.assets['dark_mode_js']}"></script>'
|
||||
}).replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
|
||||
modules_toc_str
|
||||
} else {
|
||||
symbols_toc_str
|
||||
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi
|
||||
&& vd.docs.len > 1 && d.head.name != 'README' {
|
||||
'<div class="doc-toc"><ul>' + symbols_toc_str + '</ul></div>'
|
||||
&& d.head.name != 'README' {
|
||||
'<div class="doc-toc"><ul>${symbols_toc_str}</ul></div>'
|
||||
} else {
|
||||
''
|
||||
}).replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp)).replace('{{ footer_assets }}',
|
||||
if cfg.inline_assets {
|
||||
'<script>' + vd.assets['doc_js'] + '</script>'
|
||||
'<script>${vd.assets['doc_js']}</script>'
|
||||
} else {
|
||||
'<script src="' + vd.assets['doc_js'] + '"></script>'
|
||||
'<script src="${vd.assets['doc_js']}"></script>'
|
||||
})
|
||||
return result
|
||||
}
|
||||
@ -407,12 +408,12 @@ fn doc_node_html(dn doc.DocNode, link string, head bool, include_examples bool,
|
||||
node_id = 'readme_${node_id}'
|
||||
hash_link = ' <a href="#${node_id}">#</a>'
|
||||
}
|
||||
dnw.writeln('${tabs[1]}<section id="${node_id}" class="doc-node${node_class}">')
|
||||
dnw.writeln('${tabs(2)}<section id="${node_id}" class="doc-node${node_class}">')
|
||||
if dn.name.len > 0 {
|
||||
if dn.kind == .const_group {
|
||||
dnw.write_string('${tabs[2]}<div class="title"><${head_tag}>${sym_name}${hash_link}</${head_tag}>')
|
||||
dnw.write_string('${tabs(3)}<div class="title"><${head_tag}>${sym_name}${hash_link}</${head_tag}>')
|
||||
} else {
|
||||
dnw.write_string('${tabs[2]}<div class="title"><${head_tag}>${dn.kind} ${sym_name}${hash_link}</${head_tag}>')
|
||||
dnw.write_string('${tabs(3)}<div class="title"><${head_tag}>${dn.kind} ${sym_name}${hash_link}</${head_tag}>')
|
||||
}
|
||||
if link.len != 0 {
|
||||
dnw.write_string('<a class="link" rel="noreferrer" target="_blank" href="${link}">${link_svg}</a>')
|
||||
|
1
cmd/tools/vdoc/tests/testdata/readme_in_project_root/README.md
vendored
Normal file
1
cmd/tools/vdoc/tests/testdata/readme_in_project_root/README.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
hello from readme
|
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
vendored
Normal file
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module foo
|
||||
|
||||
fn bar()
|
4
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
vendored
Normal file
4
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
hello from readme
|
||||
module foo
|
||||
|
||||
fn bar()
|
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.v
vendored
Normal file
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.v
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module foo
|
||||
|
||||
pub fn bar() {}
|
0
cmd/tools/vdoc/tests/testdata/readme_in_project_root/v.mod
vendored
Normal file
0
cmd/tools/vdoc/tests/testdata/readme_in_project_root/v.mod
vendored
Normal file
@ -52,6 +52,11 @@ fn check_path(vexe string, dir string, tests []string) int {
|
||||
cmd: '${os.quoted_path(vexe)} doc -comments ${os.quoted_path(program)}'
|
||||
out_filename: 'main.comments.out'
|
||||
)
|
||||
fails += check_output(
|
||||
program: program
|
||||
cmd: '${os.quoted_path(vexe)} doc -readme -comments ${os.quoted_path(program)}'
|
||||
out_filename: 'main.readme.comments.out'
|
||||
)
|
||||
total_fails += fails
|
||||
if fails == 0 {
|
||||
println(term.green('OK'))
|
||||
@ -71,7 +76,7 @@ fn print_compare(expected string, found string) {
|
||||
println(found)
|
||||
println('============\n')
|
||||
println('diff:')
|
||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected))
|
||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), expected, found))
|
||||
println('============\n')
|
||||
}
|
||||
|
||||
|
5
cmd/tools/vdoc/theme/.prettierrc
Normal file
5
cmd/tools/vdoc/theme/.prettierrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"printWidth": 100,
|
||||
"singleQuote": true
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
(function () {
|
||||
var html = document.getElementsByTagName('html')[0];
|
||||
if (localStorage.getItem('dark-mode') === 'true') {
|
||||
html.classList.add('dark');
|
||||
document.querySelector('html').classList.add('dark');
|
||||
}
|
||||
})();
|
||||
|
@ -86,8 +86,8 @@ html {
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Jost, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
|
||||
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-family: Jost, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
background-color: #fff;
|
||||
background-color: var(--background-color);
|
||||
color: #000;
|
||||
@ -98,7 +98,6 @@ body {
|
||||
height: 100%;
|
||||
padding-top: 56px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/** Reset for menus */
|
||||
@ -158,8 +157,6 @@ body {
|
||||
fill: var(--menu-toggle-icon-color);
|
||||
}
|
||||
.doc-nav > .heading-container {
|
||||
position: relative;
|
||||
/* IE11 */
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
@ -185,16 +182,10 @@ body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.doc-nav
|
||||
> .heading-container
|
||||
> .heading
|
||||
> .info
|
||||
> .toggle-version-container
|
||||
> #dark-mode-toggle {
|
||||
.doc-nav > .heading-container > .heading > .info > .toggle-version-container > #dark-mode-toggle {
|
||||
cursor: pointer;
|
||||
fill: #fff;
|
||||
display: flex;
|
||||
visibility: hidden;
|
||||
}
|
||||
.doc-nav
|
||||
> .heading-container
|
||||
@ -326,8 +317,8 @@ body {
|
||||
font-weight: 500;
|
||||
}
|
||||
.doc-nav > .search .result > .link > .description {
|
||||
font-family: Jost, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
|
||||
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-family: Jost, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
font-size: 0.75rem;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
@ -349,7 +340,6 @@ body {
|
||||
/* Main content */
|
||||
.doc-scrollview {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.doc-container {
|
||||
display: flex;
|
||||
@ -381,7 +371,6 @@ body {
|
||||
padding: 5rem 0 2rem 0;
|
||||
margin-top: -4rem;
|
||||
overflow: hidden;
|
||||
word-break: break-all; /* IE11 */
|
||||
word-break: break-word;
|
||||
}
|
||||
.doc-content > .doc-node.const:nth-child(2) {
|
||||
@ -418,7 +407,7 @@ body {
|
||||
background-color: var(--code-background-color);
|
||||
color: var(--attribute-text-color);
|
||||
margin-right: 0.8rem;
|
||||
font-family: "Jetbrains Mono", monospace;
|
||||
font-family: 'Jetbrains Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.doc-content > .doc-node > .attributes > .attribute-deprecated {
|
||||
@ -550,7 +539,7 @@ pre code {
|
||||
color: var(--code-default-text-color);
|
||||
font-size: 0.948em;
|
||||
text-shadow: none;
|
||||
font-family: "Jetbrains Mono", monospace;
|
||||
font-family: 'Jetbrains Mono', monospace;
|
||||
background-color: #edf2f7;
|
||||
background-color: var(--code-background-color);
|
||||
border-radius: 0.25rem;
|
||||
@ -643,14 +632,11 @@ pre {
|
||||
padding: 0rem 2rem 1rem 2rem;
|
||||
}
|
||||
.doc-toc {
|
||||
position: relative;
|
||||
/* IE11 */
|
||||
position: sticky;
|
||||
height: 100vh;
|
||||
position: -webkit-sticky;
|
||||
align-self: flex-start;
|
||||
top: 56px;
|
||||
height: auto;
|
||||
height: 100vh;
|
||||
min-width: 200px;
|
||||
width: auto;
|
||||
max-width: 300px;
|
||||
@ -702,12 +688,7 @@ pre {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
.doc-nav
|
||||
> .heading-container
|
||||
> .heading
|
||||
> .info
|
||||
> .toggle-version-container
|
||||
> #dark-mode-toggle {
|
||||
.doc-nav > .heading-container > .heading > .info > .toggle-version-container > #dark-mode-toggle {
|
||||
margin-right: auto;
|
||||
}
|
||||
.doc-nav .content.show,
|
||||
|
@ -1,96 +1,85 @@
|
||||
(function () {
|
||||
if (document.body.scrollIntoView) {
|
||||
var docnav = document.querySelector('.doc-nav');
|
||||
var active = docnav.querySelector('li.active');
|
||||
if (active) {
|
||||
active.scrollIntoView({ block: 'center', inline: 'nearest' });
|
||||
}
|
||||
}
|
||||
setupScrollSpy();
|
||||
const docnav = document.querySelector('.doc-nav');
|
||||
const active = docnav.querySelector('li.active');
|
||||
active?.scrollIntoView({ block: 'center', inline: 'nearest' });
|
||||
setupMobileToggle();
|
||||
setupDarkMode();
|
||||
setupScrollSpy();
|
||||
setupSearch();
|
||||
setupCollapse();
|
||||
})();
|
||||
|
||||
function setupScrollSpy() {
|
||||
var sectionPositions = [];
|
||||
var sections = document.querySelectorAll('section');
|
||||
sections.forEach(function (section) {
|
||||
sectionPositions.push(section.offsetTop);
|
||||
});
|
||||
var scrollPos = 0;
|
||||
window.addEventListener('scroll', function (_) {
|
||||
const sections = document.querySelectorAll('section');
|
||||
const sectionPositions = Array.from(sections).map((section) => section.offsetTop);
|
||||
let scrollPos = 0;
|
||||
window.addEventListener('scroll', () => {
|
||||
const toc = document.querySelector('.doc-toc');
|
||||
// Reset classes
|
||||
document.querySelectorAll('.doc-toc a[class="active"]').forEach(function (link) {
|
||||
link.classList.remove('active');
|
||||
});
|
||||
toc.querySelectorAll('a[class="active"]').forEach((link) => link.classList.remove('active'));
|
||||
// Set current menu link as active
|
||||
var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
for (var i = 0; i < sectionPositions.length; i++) {
|
||||
var section = sections[i];
|
||||
var position = sectionPositions[i];
|
||||
let scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
for (const [i, position] of sectionPositions.entries()) {
|
||||
if (position >= scrollPosition) {
|
||||
var link = document.querySelector('.doc-toc a[href="#' + section.id + '"]');
|
||||
const section = sections[i];
|
||||
const link = toc.querySelector('a[href="#' + section.id + '"]');
|
||||
if (link) {
|
||||
link.classList.add('active');
|
||||
var docToc = document.querySelector('.doc-toc');
|
||||
var tocHeight = docToc.clientHeight;
|
||||
var scrollTop = docToc.scrollTop;
|
||||
if ((document.body.getBoundingClientRect()).top < scrollPos && scrollTop < link.offsetTop - 10) {
|
||||
docToc.scrollTop = link.clientHeight + link.offsetTop - tocHeight + 10;
|
||||
const tocHeight = toc.clientHeight;
|
||||
const scrollTop = toc.scrollTop;
|
||||
if (
|
||||
document.body.getBoundingClientRect().top < scrollPos &&
|
||||
scrollTop < link.offsetTop - 10
|
||||
) {
|
||||
toc.scrollTop = link.clientHeight + link.offsetTop - tocHeight + 10;
|
||||
} else if (scrollTop > link.offsetTop - 10) {
|
||||
docToc.scrollTop = link.offsetTop - 10;
|
||||
toc.scrollTop = link.offsetTop - 10;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
scrollPos = (document.body.getBoundingClientRect()).top;
|
||||
scrollPos = document.body.getBoundingClientRect().top;
|
||||
});
|
||||
}
|
||||
|
||||
function setupMobileToggle() {
|
||||
var toggle = document.getElementById('toggle-menu');
|
||||
toggle.addEventListener('click', function (_) {
|
||||
var docNav = document.querySelector('.doc-nav');
|
||||
var isHidden = docNav.classList.contains('hidden');
|
||||
document.getElementById('toggle-menu').addEventListener('click', () => {
|
||||
const docNav = document.querySelector('.doc-nav');
|
||||
const isHidden = docNav.classList.contains('hidden');
|
||||
docNav.classList.toggle('hidden');
|
||||
var search = document.querySelector('.doc-nav > .search');
|
||||
console.log(search);
|
||||
var searchHasResults = search.classList.contains('has-results');
|
||||
const search = docNav.querySelector('.search');
|
||||
// console.log(search);
|
||||
const searchHasResults = search.classList.contains('has-results');
|
||||
if (isHidden && searchHasResults) {
|
||||
search.classList.remove('mobile-hidden');
|
||||
} else {
|
||||
search.classList.add('mobile-hidden');
|
||||
}
|
||||
var content = document.querySelector('.doc-nav .content');
|
||||
const content = docNav.querySelector('.content');
|
||||
content.classList.toggle('hidden');
|
||||
content.classList.toggle('show');
|
||||
});
|
||||
}
|
||||
|
||||
function setupDarkMode() {
|
||||
var html = document.getElementsByTagName('html')[0];
|
||||
var darkModeToggle = document.getElementById('dark-mode-toggle');
|
||||
darkModeToggle.addEventListener('click', function () {
|
||||
const html = document.querySelector('html');
|
||||
const darkModeToggle = document.getElementById('dark-mode-toggle');
|
||||
darkModeToggle.addEventListener('click', () => {
|
||||
html.classList.toggle('dark');
|
||||
var isDarkModeEnabled = html.classList.contains('dark');
|
||||
const isDarkModeEnabled = html.classList.contains('dark');
|
||||
localStorage.setItem('dark-mode', isDarkModeEnabled);
|
||||
darkModeToggle.setAttribute('aria-checked', isDarkModeEnabled)
|
||||
darkModeToggle.setAttribute('aria-checked', isDarkModeEnabled);
|
||||
});
|
||||
// Check if css var() is supported and enable dark mode toggle
|
||||
if (window.CSS && CSS.supports('color', 'var(--fake-var)')) {
|
||||
darkModeToggle.style.visibility = 'unset';
|
||||
}
|
||||
}
|
||||
|
||||
function setupSearch() {
|
||||
var searchInput = document.getElementById('search');
|
||||
var onInputChange = debounce(function (e) {
|
||||
var searchValue = e.target.value.toLowerCase();
|
||||
var menu = document.querySelector('.doc-nav > .content');
|
||||
var search = document.querySelector('.doc-nav > .search');
|
||||
const searchInput = document.getElementById('search');
|
||||
const onInputChange = debounce((e) => {
|
||||
const searchValue = e.target.value.toLowerCase();
|
||||
const docNav = document.querySelector('.doc-nav');
|
||||
const menu = docNav.querySelector('.content');
|
||||
const search = docNav.querySelector('.search');
|
||||
if (searchValue === '') {
|
||||
// reset to default
|
||||
menu.style.display = '';
|
||||
@ -108,96 +97,77 @@ function setupSearch() {
|
||||
search.classList.add('has-results');
|
||||
}
|
||||
// cache length for performance
|
||||
var foundModule = false;
|
||||
var searchModuleIndexLength = searchModuleIndex.length;
|
||||
var ul = document.createElement('ul');
|
||||
let foundModule = false;
|
||||
const ul = document.createElement('ul');
|
||||
search.appendChild(ul);
|
||||
for (var i = 0; i < searchModuleIndexLength; i++) {
|
||||
for (const [i, title] of searchModuleIndex.entries()) {
|
||||
// no toLowerCase needed because modules are always lowercase
|
||||
var title = searchModuleIndex[i];
|
||||
if (title.indexOf(searchValue) === -1) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
foundModule = true;
|
||||
// [description, link]
|
||||
var data = searchModuleData[i];
|
||||
var description = data[0];
|
||||
var link = data[1];
|
||||
var el = createSearchResult({
|
||||
link: link,
|
||||
title: title,
|
||||
description: description,
|
||||
const data = searchModuleData[i];
|
||||
const el = createSearchResult({
|
||||
badge: 'module',
|
||||
description: data[0],
|
||||
link: data[1],
|
||||
title: title,
|
||||
});
|
||||
ul.appendChild(el);
|
||||
}
|
||||
if (foundModule) {
|
||||
var hr = document.createElement('hr');
|
||||
const hr = document.createElement('hr');
|
||||
hr.classList.add('separator');
|
||||
search.appendChild(hr);
|
||||
}
|
||||
var searchIndexLength = searchIndex.length;
|
||||
var results = [];
|
||||
for (var i = 0; i < searchIndexLength; i++) {
|
||||
var title = searchIndex[i];
|
||||
let results = [];
|
||||
for (const [i, title] of searchIndex.entries()) {
|
||||
if (title.toLowerCase().indexOf(searchValue) === -1) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
// [badge, description, link]
|
||||
var data = searchData[i];
|
||||
var badge = data[0];
|
||||
var description = data[1];
|
||||
var link = data[2];
|
||||
var prefix = data[3];
|
||||
const data = searchData[i];
|
||||
results.push({
|
||||
badge: badge,
|
||||
description: description,
|
||||
link: link,
|
||||
title: prefix + ' ' + title,
|
||||
badge: data[0],
|
||||
description: data[1],
|
||||
link: data[2],
|
||||
title: data[3] + ' ' + title,
|
||||
});
|
||||
}
|
||||
results.sort(function (a, b) {
|
||||
if (a.title < b.title) {
|
||||
return -1;
|
||||
}
|
||||
if (a.title > b.title) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
results.sort((a, b) => (a.title < b.title ? -1 : a.title > b.title ? 1 : 0));
|
||||
const ul_ = document.createElement('ul');
|
||||
search.appendChild(ul_);
|
||||
results.forEach((result) => {
|
||||
const el = createSearchResult(result);
|
||||
ul_.appendChild(el);
|
||||
});
|
||||
var ul = document.createElement('ul');
|
||||
search.appendChild(ul);
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var result = results[i];
|
||||
var el = createSearchResult(result);
|
||||
ul.appendChild(el);
|
||||
}
|
||||
}
|
||||
});
|
||||
searchInput.addEventListener('input', onInputChange);
|
||||
}
|
||||
|
||||
function createSearchResult(data) {
|
||||
var li = document.createElement('li');
|
||||
const li = document.createElement('li');
|
||||
li.classList.add('result');
|
||||
var a = document.createElement('a');
|
||||
const a = document.createElement('a');
|
||||
a.href = data.link;
|
||||
a.classList.add('link');
|
||||
li.appendChild(a);
|
||||
var defintion = document.createElement('div');
|
||||
const defintion = document.createElement('div');
|
||||
defintion.classList.add('definition');
|
||||
a.appendChild(defintion);
|
||||
if (data.description) {
|
||||
var description = document.createElement('div');
|
||||
const description = document.createElement('div');
|
||||
description.classList.add('description');
|
||||
description.textContent = data.description;
|
||||
a.appendChild(description);
|
||||
}
|
||||
var title = document.createElement('span');
|
||||
const title = document.createElement('span');
|
||||
title.classList.add('title');
|
||||
title.textContent = data.title;
|
||||
defintion.appendChild(title);
|
||||
var badge = document.createElement('badge');
|
||||
const badge = document.createElement('badge');
|
||||
badge.classList.add('badge');
|
||||
badge.textContent = data.badge;
|
||||
defintion.appendChild(badge);
|
||||
@ -205,30 +175,29 @@ function createSearchResult(data) {
|
||||
}
|
||||
|
||||
function setupCollapse() {
|
||||
var dropdownArrows = document.querySelectorAll('.dropdown-arrow');
|
||||
for (var i = 0; i < dropdownArrows.length; i++) {
|
||||
var dropdownArrow = dropdownArrows[i];
|
||||
dropdownArrow.addEventListener('click', function (e) {
|
||||
var parent = e.target.parentElement.parentElement.parentElement;
|
||||
const dropdownArrows = document.querySelectorAll('.dropdown-arrow');
|
||||
dropdownArrows.forEach((arrow) => {
|
||||
arrow.addEventListener('click', (e) => {
|
||||
const parent = e.target.parentElement.parentElement.parentElement;
|
||||
parent.classList.toggle('open');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function debounce(func, timeout) {
|
||||
var timer;
|
||||
let timer;
|
||||
return (...args) => {
|
||||
const next = () => func(...args);
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
document.addEventListener('keypress', (ev) => {
|
||||
if (ev.key == '/') {
|
||||
let search = document.getElementById('search');
|
||||
const search = document.getElementById('search');
|
||||
ev.preventDefault();
|
||||
search.focus();
|
||||
}
|
||||
|
@ -1,22 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{{ title }} | vdoc</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Jost:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap" rel="stylesheet">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
|
||||
<link rel="manifest" href="site.webmanifest">
|
||||
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Jost:wght@300;400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png" />
|
||||
<link rel="manifest" href="site.webmanifest" />
|
||||
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
{{ head_assets }}
|
||||
</head>
|
||||
|
||||
@ -30,11 +35,18 @@
|
||||
<div class="module">{{ head_name }}</div>
|
||||
<div class="toggle-version-container">
|
||||
<span>{{ version }}</span>
|
||||
<div id="dark-mode-toggle" role="switch" aria-checked="false" aria-label="Toggle dark mode">{{ light_icon }}{{ dark_icon }}</div>
|
||||
<div
|
||||
id="dark-mode-toggle"
|
||||
role="switch"
|
||||
aria-checked="false"
|
||||
aria-label="Toggle dark mode"
|
||||
>
|
||||
{{ light_icon }}{{ dark_icon }}
|
||||
</div>
|
||||
</div>
|
||||
{{ menu_icon }}
|
||||
</div>
|
||||
<input type="text" id="search" placeholder="Search... (beta)" autocomplete="off">
|
||||
<input type="text" id="search" placeholder="Search... (beta)" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<nav class="search hidden"></nav>
|
||||
@ -48,9 +60,7 @@
|
||||
<div class="doc-container">
|
||||
<div class="doc-content">
|
||||
{{ contents }}
|
||||
<div class="footer">
|
||||
{{ footer_content }}
|
||||
</div>
|
||||
<div class="footer">{{ footer_content }}</div>
|
||||
</div>
|
||||
{{ right_content }}
|
||||
</div>
|
||||
@ -59,5 +69,4 @@
|
||||
{{ footer_assets }}
|
||||
<script async src="search_index.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
30
cmd/tools/vdoc/theme/normalize.css
vendored
30
cmd/tools/vdoc/theme/normalize.css
vendored
@ -91,24 +91,24 @@ select {
|
||||
}
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
[type='button'],
|
||||
[type='reset'],
|
||||
[type='submit'] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
[type='button']::-moz-focus-inner,
|
||||
[type='reset']::-moz-focus-inner,
|
||||
[type='submit']::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
[type='button']:-moz-focusring,
|
||||
[type='reset']:-moz-focusring,
|
||||
[type='submit']:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
@ -133,23 +133,23 @@ textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
[type='checkbox'],
|
||||
[type='radio'] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
[type='number']::-webkit-inner-spin-button,
|
||||
[type='number']::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type="search"] {
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
[type='search']::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ const (
|
||||
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
|
||||
vexe = os.getenv_opt('VEXE') or { @VEXE }
|
||||
vroot = os.dir(vexe)
|
||||
tabs = ['\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t']
|
||||
)
|
||||
|
||||
enum OutputType {
|
||||
@ -233,6 +232,9 @@ fn (vd VDoc) get_readme(path string) string {
|
||||
}
|
||||
}
|
||||
if fname == '' {
|
||||
if path.all_after_last(os.path_separator) == 'src' {
|
||||
return vd.get_readme(path.all_before_last(os.path_separator))
|
||||
}
|
||||
return ''
|
||||
}
|
||||
readme_path := os.join_path(path, '${fname}.md')
|
||||
|
@ -312,7 +312,7 @@ fn run_repl(workdir string, vrepl_prefix string) int {
|
||||
if line == '' && oline.ends_with('\n') {
|
||||
continue
|
||||
}
|
||||
if line.len <= -1 || line == '' || line == 'exit' {
|
||||
if line.len <= -1 || line == 'exit' {
|
||||
break
|
||||
}
|
||||
if exit_pos := line.index('exit') {
|
||||
|
@ -180,6 +180,15 @@ fn get_all_commands() []Command {
|
||||
okmsg: 'V can compile 2048 with -skip-unused.'
|
||||
rmfile: 'examples/2048/2048'
|
||||
}
|
||||
if _ := os.find_abs_path_of_executable('emcc') {
|
||||
res << Command{
|
||||
line: '${vexe} -os wasm32_emscripten examples/2048'
|
||||
okmsg: 'V can compile 2048 with -os wasm32_emscripten, using emcc.'
|
||||
rmfile: 'examples/2048/2048'
|
||||
}
|
||||
} else {
|
||||
println('> emcc not found, skipping `v -os wasm32_emscripten examples/2048`.')
|
||||
}
|
||||
res << Command{
|
||||
line: '${vexe} -skip-unused -live examples/hot_reload/bounce.v'
|
||||
okmsg: 'V can compile the hot code reloading bounce.v example with both: -skip-unused -live'
|
||||
|
@ -52,7 +52,7 @@ fn check_path(vexe string, dir string, tests []string) int {
|
||||
println(found)
|
||||
println('============\n')
|
||||
println('diff:')
|
||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected))
|
||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), expected, found))
|
||||
println('============\n')
|
||||
nb_fail++
|
||||
} else {
|
||||
|
@ -1,43 +1,48 @@
|
||||
# Serve
|
||||
# JS DOM Cube
|
||||
|
||||
This project has a no dependence serve in `./server.js` path.
|
||||
That can be run with `node` command after build.
|
||||
## Compiling
|
||||
|
||||
or just run: `npm run start`
|
||||
|
||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
||||
|
||||
# Compiling
|
||||
```
|
||||
v -b js_browser examples/js_dom_cube/cube.js.v
|
||||
```
|
||||
|
||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
||||
Then you can open `index.html` with your favourite browser.
|
||||
# Serve examples
|
||||
Then you can open `index.html` in your favorite browser.
|
||||
|
||||
## Serve Examples
|
||||
|
||||
### JS Server
|
||||
|
||||
> **NOTE**\
|
||||
> The JS server example in the following steps requires Node.js.
|
||||
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||
|
||||
Initialize the example as a Node project
|
||||
|
||||
```
|
||||
cd examples/js_dom_cube/
|
||||
npm init -y
|
||||
```
|
||||
|
||||
Add a `start` and `build` script to the generated `./package.json` file.
|
||||
|
||||
### JS server
|
||||
After run `npm init -y` code and genared `./package.json`
|
||||
You can put `start` and `build` at script in jason leaf.
|
||||
`path './package.json'`
|
||||
```json
|
||||
"scripts": {
|
||||
...
|
||||
"start": "npm run build && node server.js",
|
||||
"build": "v -b js_browser cube.js.v"
|
||||
},
|
||||
|
||||
```
|
||||
here is the pure javascript server code
|
||||
`path './server.js'`
|
||||
|
||||
Below is an example of a Node.js server without external dependencies.
|
||||
You can use it for `./server.js`.
|
||||
|
||||
```javascript
|
||||
const http = require("http");
|
||||
const fs = require("fs");
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
const host = "localhost";
|
||||
const host = 'localhost';
|
||||
const port = 3000;
|
||||
|
||||
const reqListener = function (req, res) {
|
||||
@ -64,7 +69,7 @@ const reqListener = function (req, res) {
|
||||
'.ttf': 'application/font-ttf',
|
||||
'.eot': 'application/vnd.ms-fontobject',
|
||||
'.otf': 'application/font-otf',
|
||||
'.wasm': 'application/wasm'
|
||||
'.wasm': 'application/wasm',
|
||||
};
|
||||
|
||||
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||
@ -76,13 +81,11 @@ const reqListener = function (req, res) {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content, 'utf-8');
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.writeHead(500);
|
||||
res.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.writeHead(200, { 'Content-Type': contentType });
|
||||
res.end(content, 'utf-8');
|
||||
}
|
||||
@ -93,25 +96,20 @@ const server = http.createServer(reqListener);
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Server is running on http://${host}:${port}`);
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
This project has a no dependence serve in `./server.js` path.
|
||||
That can be run with `node` command after build.
|
||||
|
||||
or just run: `npm run start`
|
||||
|
||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
||||
Now you can build and run the project with the added scripts.
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
$ cd examples/js_dom_draw/
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
|
||||
### V server
|
||||
```v ignore
|
||||
|
||||
The example below uses `vweb` to serve the project.
|
||||
|
||||
```v
|
||||
module main
|
||||
|
||||
import vweb
|
||||
@ -130,7 +128,7 @@ fn main() {
|
||||
}
|
||||
|
||||
pub fn (mut app App) before_request() {
|
||||
// This build server json files
|
||||
// Build the cube.js javascript file
|
||||
os.execute_or_panic('v -b js_browser cube.js.v ')
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,50 @@
|
||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
||||
# JS DOM Draw
|
||||
|
||||
# Compiling
|
||||
```
|
||||
Drawing with mouse events using the DOM API. Adopted from MDN examples.
|
||||
|
||||
## Compiling
|
||||
|
||||
```sh
|
||||
v -b js_browser examples/js_dom_draw/draw.js.v
|
||||
```
|
||||
|
||||
Then you can open `index.html` with your favourite browser.
|
||||
# Serve examples
|
||||
Then you can open `index.html` in your favorite browser.
|
||||
|
||||
## Serve Examples
|
||||
|
||||
### JS Server
|
||||
|
||||
> **NOTE**\
|
||||
> The JS server example in the following steps requires Node.js.
|
||||
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||
|
||||
Initialize the example as a Node project
|
||||
|
||||
```
|
||||
cd examples/js_dom_draw/
|
||||
npm init -y
|
||||
```
|
||||
|
||||
Add a `start` and `build` script to the generated `./package.json` file.
|
||||
|
||||
### JS server
|
||||
After run `npm init -y` code and genared `./package.json`
|
||||
You can put `start` and `build` at script in jason leaf.
|
||||
`path './package.json'`
|
||||
```json
|
||||
"scripts": {
|
||||
...
|
||||
"start": "npm run build && node server.js",
|
||||
"build": "v -b js_browser draw.js.v"
|
||||
},
|
||||
|
||||
```
|
||||
here is the pure javascript server code
|
||||
`path './server.js'`
|
||||
|
||||
Below is an example of a Node.js server without external dependencies.
|
||||
You can use it for `./server.js`.
|
||||
|
||||
```javascript
|
||||
const http = require("http");
|
||||
const fs = require("fs");
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
const host = "localhost";
|
||||
const host = 'localhost';
|
||||
const port = 3000;
|
||||
|
||||
const reqListener = function (req, res) {
|
||||
@ -54,7 +71,7 @@ const reqListener = function (req, res) {
|
||||
'.ttf': 'application/font-ttf',
|
||||
'.eot': 'application/vnd.ms-fontobject',
|
||||
'.otf': 'application/font-otf',
|
||||
'.wasm': 'application/wasm'
|
||||
'.wasm': 'application/wasm',
|
||||
};
|
||||
|
||||
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||
@ -66,13 +83,11 @@ const reqListener = function (req, res) {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end(content, 'utf-8');
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.writeHead(500);
|
||||
res.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.writeHead(200, { 'Content-Type': contentType });
|
||||
res.end(content, 'utf-8');
|
||||
}
|
||||
@ -83,25 +98,20 @@ const server = http.createServer(reqListener);
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Server is running on http://${host}:${port}`);
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
This project has a no dependence serve in `./server.js` path.
|
||||
That can be run with `node` command after build.
|
||||
|
||||
or just run: `npm run start`
|
||||
|
||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
||||
Now you can build and run the project with the added scripts.
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
$ cd examples/js_dom_draw/
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
|
||||
### V server
|
||||
```v ignore
|
||||
|
||||
The example below uses `vweb` to serve the project.
|
||||
|
||||
```v
|
||||
module main
|
||||
|
||||
import vweb
|
||||
@ -120,7 +130,7 @@ fn main() {
|
||||
}
|
||||
|
||||
pub fn (mut app App) before_request() {
|
||||
// This build server json files
|
||||
// Build the draw.js javascript file
|
||||
os.execute_or_panic('v -b js_browser draw.js.v ')
|
||||
}
|
||||
|
||||
|
@ -1,35 +1,57 @@
|
||||
# JS DOM Benchmark Chart
|
||||
|
||||
![image](https://user-images.githubusercontent.com/63821277/186010833-2ea36f3a-4738-4025-9b23-ac62afe74b81.png)
|
||||
|
||||
# To run app
|
||||
## From root
|
||||
- run typescript project
|
||||
`npm i --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
||||
`npm run start:dev --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
||||
## Running the App
|
||||
|
||||
- run v project
|
||||
`v run examples/js_dom_draw_bechmark_chart/v_vweb_orm `
|
||||
> **NOTE**\
|
||||
> The following steps require Node.js.
|
||||
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||
|
||||
- running v chart
|
||||
`cd examples/js_dom_draw_bechmark_chart/chart && v run .`
|
||||
The steps below assume that your current directory path is the examples project directory.
|
||||
|
||||
Dockerfile
|
||||
[docker build]=> Docker image
|
||||
[docker run]=> Docker container
|
||||
```
|
||||
cd examples/js_dom_draw_bechmark_chart
|
||||
```
|
||||
|
||||
`sudo docker build -t <name> .`
|
||||
Execute the following commands in separate terminal instances.
|
||||
|
||||
`sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>`
|
||||
Run the Benchmarks Typescript Part
|
||||
|
||||
`v run .`
|
||||
```sh
|
||||
npm i --prefix typescript_vanilla_typeorm
|
||||
npm run start:dev --prefix typescript_vanilla_typeorm
|
||||
```
|
||||
|
||||
A message like `[Vweb] Running app on http://localhost:3001/` should appear
|
||||
Run the Benchmarks V Part
|
||||
|
||||
`exit`
|
||||
```sh
|
||||
v run v_vweb_orm
|
||||
```
|
||||
|
||||
# To implement new benchmarks in v
|
||||
Run the Chart
|
||||
|
||||
In `examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v` path
|
||||
Create a route returning a `Response` struct like:
|
||||
```
|
||||
cd chart/ && v run .
|
||||
```
|
||||
|
||||
## Dockerfile
|
||||
|
||||
> [docker build] => Docker image\
|
||||
> [docker run] => Docker container
|
||||
|
||||
```sh
|
||||
sudo docker build -t <name> .
|
||||
sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>
|
||||
v run .
|
||||
# A message like `[Vweb] Running app on http://localhost:3001/` should appear
|
||||
exit
|
||||
```
|
||||
|
||||
## Implementing New Benchmarks in V
|
||||
|
||||
In `v_vweb_orm/src/main.v`, create a route that returns a `Response` struct.
|
||||
|
||||
```v ignore
|
||||
['/sqlite-memory/:count']
|
||||
@ -71,12 +93,11 @@ pub fn (mut app App) sqlite_memory(count int) vweb.Result {
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In `examples/chart/services.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
In `chart/main.v`, create a service to request the benchmark data and decode the response as
|
||||
`FrameworkBenchmarkResponse`.
|
||||
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'
|
||||
@ -86,26 +107,13 @@ fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
}
|
||||
```
|
||||
|
||||
In `examples/chart/main.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
|
||||
return framework_benchmark_response
|
||||
}
|
||||
```
|
||||
Then, update:
|
||||
`insert_framework_benchmark_times()`;
|
||||
`select_framework_benchmark_times()`;
|
||||
`update_framework_benchmark_times()`.
|
||||
with the new function
|
||||
Then update `insert_framework_benchmark_times()`, `select_framework_benchmark_times()` and
|
||||
`update_framework_benchmark_times()` to include the `numbers := FrameworkPlatform{` for the newly
|
||||
added function.
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
||||
# ROADMAP
|
||||
02/09/2022
|
||||
|
||||
- [ ] select bench (easy)
|
||||
- [ ] vsql (easy)
|
||||
|
21
examples/ssl_server/cert/ca.crt
Normal file
21
examples/ssl_server/cert/ca.crt
Normal file
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDbTCCAlWgAwIBAgIUTbcFMmB84wg6eqDRJbmo49aOTdMwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA3MzAxNzM0MThaGA8yMDUw
|
||||
MTIxNDE3MzQxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
|
||||
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBANPfvg3G/3+j2NX5qDf0gw9iSnCiUa1T1inxlnfP
|
||||
vMVINDkH22yUSeValyuIrpF94m23ANo0yOXQJxbIt8PbwaRYTq1EzxlGkkXUHob3
|
||||
m1qJLH1qLacJeLMPj3J7kUXVWL65Qb7d2gtwMvegJ5I5U4ntLjXAmIV4z4PpZ2tP
|
||||
MsERacj/alb0EDS77P4JcbRzYvP/3FyFokel5TF/nLV3hXc5Eu6LjCzbEEus1MLd
|
||||
rgcpODUlw8Gf0M0nAjxijVpXAVo6XYRQ/00+zjPaKxjtQ/ds/O7zRTNxnUVvh1oH
|
||||
Pnif9rkVBLkVjmSU/C7jvAKqrWPU9b24hXpnfSIirkn3tO8CAwEAAaNTMFEwHQYD
|
||||
VR0OBBYEFPx8Ivgj5Gi4XyHFZ/zGgZU4kGc7MB8GA1UdIwQYMBaAFPx8Ivgj5Gi4
|
||||
XyHFZ/zGgZU4kGc7MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
|
||||
AJYSckwJSZlj8baEMvAJLs55Bm5wR1QZaj7mz8tBxK8zd9PdW3fTebil6jtGLpXT
|
||||
CHi+vaa5HsM2QXnYaZCSlawD3WWZ+LZ9lJVuWC+iWfRq6TC/gEd+3zCE70CeeAAu
|
||||
0pZC2Luvvgm5a6qfKoA4lEvlB2Yr0pX2GhXYOGvIeSMWpohKyKmiJEi83kJvzjnl
|
||||
BsFIR6FB1wO2+nrfLCzmjwPQx0ie2h+fPwf5Y2C0pPBYVwXpP94EEZW+lQgPXx5I
|
||||
6X8HPVNMtu4lToe746ctQlA4YDwge5mmiGUgF95Y3/O9Z2vjPqeN826oR89YFFZF
|
||||
JFtrrBskGW5fOzKOXLc96pE=
|
||||
-----END CERTIFICATE-----
|
24
examples/ssl_server/cert/client.crt
Normal file
24
examples/ssl_server/cert/client.crt
Normal file
@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEEzCCAvsCFG64Q2g46jZb3kRbDOJWX/BwjSp5MA0GCSqGSIb3DQEBCwUAMEUx
|
||||
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
|
||||
cm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDQzWhgPMjA1MDEyMTQx
|
||||
NzM0NDNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
|
||||
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUA
|
||||
A4ICDwAwggIKAoICAQDqDmHNMesBQ6S/ZU+xW4sO18Q+WfvXEaMdEfN5D8wyazP3
|
||||
mA7VTsNjliHrLFDiaTX9dR9Js+SwqmLpZTZoxBzn6wDuuM9fswvISnVERgZZdFas
|
||||
lkgci4iXVE2TREEqh6Ak4CAUyGiBhHm1CaT7txvq7wTghs+cgDR5hItK7EpxD7gv
|
||||
jc1sNco9Ha1GecUB0L4fCmp3ss88vvDU4ta4eLTsW/SZbTKRMawih4hp00d0v83s
|
||||
Of5iIP6kWsM9X5Oe2Fm5XaObMlCdWHIBP2aB5i2ZqYUKTl8uKExpeobcsmpvHiSb
|
||||
tAAaeFo/5shyCAXx/i55KYA2oRm71XeIBnllIBMEfKPV3AReO6p+MZFnioPxUWY0
|
||||
gWqlSzsoLJ6NxHYWeC15OQhKQ6jEO7u3SAivacG5VVEywQ7EiY3b+ncwcZt9QK8q
|
||||
UckwwnbWHZJwJcp0vHj3/Mmvawm1dWR3CVauFW3ze/l3Ik92wJBDkULhv6r07zfv
|
||||
SlL2Am7+wPWfeOomx+Kh/rnGcXATcH17dVFH/mjhTjclOuM38e7oGoQhm9lZ9kaD
|
||||
wIuu1X0+XutuY55uze9yVY9qRSIJraBuZ9mreVIVj9FG0kpVplrTr7oBlGA1Nc3i
|
||||
1IuilE36T4qmP50WzJ6Yy38+J7My23bUyyOXIFhX/LTpPVjhZq5tVH+WmmqW0wID
|
||||
AQABMA0GCSqGSIb3DQEBCwUAA4IBAQAbD+EVc4Ev7uXKUQV0s3nETp2odz1G8eZ/
|
||||
drAVnWJpZEeWW98ZeVfyYglqWc9G8McYpiKeac9WF+gga8F2Cn3RjMvufqr0Ggcy
|
||||
byytgJeLolukhTV/JJk8o+CUAB2xgk8+DVEiZ+7G4L/4V613VmL1B+jRHWknO/Js
|
||||
uArppuSduvmkakWOGMBGLUPUcep/vIepHByjOeq1czsdrsLokjBXjMAwXAVRSkBs
|
||||
mazD9yK95R5oG0KDmIPpfDddwvp7Xq4t3pTtMwXPYaDG+sPovsGsGYRkTnouOlKh
|
||||
ae4/jRb8ut9AqOxZRUsBzT8MJXg4cFec8qrhPe3abzxN4amqOxlj
|
||||
-----END CERTIFICATE-----
|
51
examples/ssl_server/cert/client.key
Normal file
51
examples/ssl_server/cert/client.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
26
examples/ssl_server/cert/server.crt
Normal file
26
examples/ssl_server/cert/server.crt
Normal file
@ -0,0 +1,26 @@
|
||||
No extensions in certificate
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEOTCCAyECFG64Q2g46jZb3kRbDOJWX/BwjSp4MA0GCSqGSIb3DQEBCwUAMEUx
|
||||
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
|
||||
cm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDE4WhgPMjA1MDEyMTQx
|
||||
NzM0MThaMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYD
|
||||
VQQHDAtMb3MgQW5nZWxlczEdMBsGA1UECgwUQ2F0YWx5c3QgRGV2ZWxvcG1lbnQx
|
||||
EjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
|
||||
ggIBAKUcJ5cizbhreUlC0plQngCeE+/ysZJo8TmnhEF4cFnTVCHmvzz7f5w7/Zma
|
||||
4maRzE3KT52qSA2PkX6Wr9RgnM93K93a3dfiUHaZ+DbWFnb1w/gp7TG5bgvwfjcb
|
||||
KVnkP+BIMbT90kQrLI0H89LrouvCHDvl74EvAdyYgupLTdjZ5Q5Xe9P5rUhLajw6
|
||||
iN8+NtfrQh2hDOWnbg9nQK/zjIVvvvjMQOUzda9Rq4ViAphiLNufojQhHJrlIpkP
|
||||
oR+YENiDXRcaire5RVWjzfoQGDbTJLJL8fNV1HMjJArUuCg8yIyL1wooe+XWqscg
|
||||
MzJoiCjSdai5zTF+lzcBLrm0olqB7YDCHS3x3K4C3DDRSoyFSEHRQpbSQbc6jTo6
|
||||
TuWcC9o/5fIMzzHrahqoRZG7syFyHYNtezhsFobqMX4E15gV6tBf6CMpTlXMH3ss
|
||||
DreZl900n1UcNtp7aQw2JIdRrLMW2I6UAit1o/FBYjkg/QCqPL7lw1nv0COraI74
|
||||
CU+I7opYJJgEalOkZciapB6ARMgWD1/J9qO4q98H0jETP1bh78lwLPxRe1W5fukD
|
||||
YCazJONIt4Bgdff8C2r+KhEoWQxK5VnjIdbL9E1nxscPr/4U77siCmHKdPINCrsD
|
||||
CWqxUHiuyJmkw9NCrerZoIxTBFAUc+sdibvq1M528jf1IvXXAgMBAAEwDQYJKoZI
|
||||
hvcNAQELBQADggEBAGoxRyyY+YraVOlFMzmyf+TeCQVibOJvKmY/HUjqCujgoj6o
|
||||
7UwYDAPyfzuVerDj2IzJ9bFB818iOIQUaO8Gw70EOzDifZFCm9/pET3SD7aGd4Kk
|
||||
DjCbjml/MNidVezPXNcdAM+XJ56jd2owk/pB4jaw3bkNcmn0aSnFg421fZibrTcS
|
||||
VRPCHIvV8gSqJk9ENO5EGIGU1VmTR909aIYB2fYyyW/1fyP/gn7d1Afy8CimZ1uD
|
||||
mUl5qQ5/CY378MmnODiGhsHJeH+ws77yLPwnh8eVtISwYMu9qfNRYFnotK7a5mxU
|
||||
CWpoSR77NmCUCQOarzb34soL2zZlIK9Lx+4VQPo=
|
||||
-----END CERTIFICATE-----
|
51
examples/ssl_server/cert/server.key
Normal file
51
examples/ssl_server/cert/server.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
17
examples/ssl_server/client.v
Normal file
17
examples/ssl_server/client.v
Normal file
@ -0,0 +1,17 @@
|
||||
import io
|
||||
import os
|
||||
import net.mbedtls
|
||||
|
||||
fn main() {
|
||||
mut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{
|
||||
verify: os.resource_abs_path('cert/ca.crt')
|
||||
cert: os.resource_abs_path('cert/client.crt')
|
||||
cert_key: os.resource_abs_path('cert/client.key')
|
||||
validate: true
|
||||
})!
|
||||
|
||||
client.dial('localhost', 8443)!
|
||||
client.write_string('GET / HTTP/1.1\r\n\r\n')!
|
||||
mut reader := io.new_buffered_reader(reader: client)
|
||||
println(reader.read_line()!)
|
||||
}
|
20
examples/ssl_server/server.v
Normal file
20
examples/ssl_server/server.v
Normal file
@ -0,0 +1,20 @@
|
||||
import io
|
||||
import os
|
||||
import net.mbedtls
|
||||
|
||||
fn main() {
|
||||
mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{
|
||||
verify: os.resource_abs_path('cert/ca.crt')
|
||||
cert: os.resource_abs_path('cert/server.crt')
|
||||
cert_key: os.resource_abs_path('cert/server.key')
|
||||
validate: true // mTLS
|
||||
})!
|
||||
|
||||
mut client := server.accept()!
|
||||
mut reader := io.new_buffered_reader(reader: client)
|
||||
mut request := reader.read_line()!
|
||||
println(request)
|
||||
client.write_string('HTTP/1.1 200 OK\r\n')!
|
||||
client.shutdown()!
|
||||
server.shutdown()!
|
||||
}
|
@ -49,7 +49,7 @@ V projects can be created anywhere and don't need to have a certain structure:
|
||||
```bash
|
||||
mkdir blog
|
||||
cd blog
|
||||
v init
|
||||
touch blog.v
|
||||
```
|
||||
|
||||
First, let's create a simple hello world website:
|
||||
@ -203,11 +203,11 @@ since a DB connection doesn't have to be set up for each request.
|
||||
// blog.v
|
||||
fn main() {
|
||||
mut app := App{
|
||||
db: sqlite.connect(':memory:') or { panic(err) }
|
||||
db: sqlite.connect(':memory:')!
|
||||
}
|
||||
sql app.db {
|
||||
create table Article
|
||||
}
|
||||
}!
|
||||
|
||||
first_article := Article{
|
||||
title: 'Hello, world!'
|
||||
@ -222,7 +222,7 @@ fn main() {
|
||||
sql app.db {
|
||||
insert first_article into Article
|
||||
insert second_article into Article
|
||||
}
|
||||
}!
|
||||
vweb.run(app, 8080)
|
||||
}
|
||||
```
|
||||
@ -242,7 +242,7 @@ struct Article {
|
||||
pub fn (app &App) find_all_articles() []Article {
|
||||
return sql app.db {
|
||||
select from Article
|
||||
}
|
||||
} or { panic(err) }
|
||||
}
|
||||
```
|
||||
|
||||
@ -289,7 +289,7 @@ For example, if we only wanted to find articles with ids between 100 and 200, we
|
||||
|
||||
return sql app.db {
|
||||
select from Article where id >= 100 && id <= 200
|
||||
}
|
||||
} or { panic(err) }
|
||||
```
|
||||
|
||||
Retrieving a single article is very simple:
|
||||
@ -299,7 +299,7 @@ Retrieving a single article is very simple:
|
||||
pub fn (app &App) retrieve_article() ?Article {
|
||||
return sql app.db {
|
||||
select from Article limit 1
|
||||
}
|
||||
} or { panic(err) }[0]
|
||||
}
|
||||
```
|
||||
|
||||
@ -308,9 +308,8 @@ bad queries will always be handled by the developer:
|
||||
|
||||
```v ignore
|
||||
// article.v
|
||||
article := app.retrieve_article(10) or {
|
||||
app.text('Article not found')
|
||||
return
|
||||
article := app.retrieve_article() or {
|
||||
return app.text('Article not found')
|
||||
}
|
||||
```
|
||||
|
||||
@ -349,7 +348,7 @@ pub fn (mut app App) new_article(title string, text string) vweb.Result {
|
||||
println(article)
|
||||
sql app.db {
|
||||
insert article into Article
|
||||
}
|
||||
} or { panic(err) }
|
||||
return app.redirect('/')
|
||||
}
|
||||
```
|
||||
@ -402,7 +401,7 @@ If one wants to persist data they need to use a file instead of memory SQLite Da
|
||||
Replace the db setup code with this instead:
|
||||
|
||||
```
|
||||
db: sqlite.connect('blog.db') or { panic(err) }
|
||||
db: sqlite.connect('blog.db')!
|
||||
```
|
||||
|
||||
As we can see it attempts to open a file in the current directory named `blog.db`.
|
||||
|
@ -865,7 +865,7 @@ pub fn (s string) split_nth(delim string, nth int) []string {
|
||||
i = 1
|
||||
for ch in s {
|
||||
if nth > 0 && i >= nth {
|
||||
res << s[i..]
|
||||
res << s[i - 1..]
|
||||
break
|
||||
}
|
||||
res << ch.ascii_str()
|
||||
@ -938,7 +938,7 @@ pub fn (s string) rsplit_nth(delim string, nth int) []string {
|
||||
0 {
|
||||
for i >= 0 {
|
||||
if nth > 0 && res.len == nth - 1 {
|
||||
res << s[..i]
|
||||
res << s[..i + 1]
|
||||
break
|
||||
}
|
||||
res << s[i].ascii_str()
|
||||
|
@ -183,6 +183,15 @@ fn test_split_nth() {
|
||||
assert e.split_nth(',,', 3).len == 3
|
||||
assert e.split_nth(',', -1).len == 12
|
||||
assert e.split_nth(',', 3).len == 3
|
||||
f := '1:2:3'
|
||||
assert f.split_nth(':', 2) == ['1', '2:3']
|
||||
assert f.rsplit_nth(':', 2) == ['3', '1:2']
|
||||
g := '123'
|
||||
assert g.split_nth('', 2) == ['1', '23']
|
||||
assert g.rsplit_nth('', 2) == ['3', '12']
|
||||
h := ''
|
||||
assert h.split_nth('', 2) == []
|
||||
assert h.rsplit_nth('', 2) == []
|
||||
}
|
||||
|
||||
fn test_rsplit_nth() {
|
||||
|
@ -18,9 +18,9 @@ pub mut:
|
||||
description string
|
||||
man_description string
|
||||
version string
|
||||
pre_execute FnCommandCallback
|
||||
execute FnCommandCallback
|
||||
post_execute FnCommandCallback
|
||||
pre_execute FnCommandCallback = unsafe { nil }
|
||||
execute FnCommandCallback = unsafe { nil }
|
||||
post_execute FnCommandCallback = unsafe { nil }
|
||||
disable_help bool
|
||||
disable_man bool
|
||||
disable_version bool
|
||||
|
@ -151,17 +151,17 @@ pub fn new() &Digest {
|
||||
}
|
||||
|
||||
// new512_224 returns a new Digest (implementing hash.Hash) computing the SHA-512/224 checksum.
|
||||
fn new512_224() &Digest {
|
||||
pub fn new512_224() &Digest {
|
||||
return new_digest(.sha512_224)
|
||||
}
|
||||
|
||||
// new512_256 returns a new Digest (implementing hash.Hash) computing the SHA-512/256 checksum.
|
||||
fn new512_256() &Digest {
|
||||
pub fn new512_256() &Digest {
|
||||
return new_digest(.sha512_256)
|
||||
}
|
||||
|
||||
// new384 returns a new Digest (implementing hash.Hash) computing the SHA-384 checksum.
|
||||
fn new384() &Digest {
|
||||
pub fn new384() &Digest {
|
||||
return new_digest(.sha384)
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,22 @@ module datatypes
|
||||
|
||||
[heap]
|
||||
struct BloomFilter[T] {
|
||||
hash_func fn (T) u32 // hash function, input [T] , output u32
|
||||
// TODO V bug
|
||||
hash_func fn (T) u32 = unsafe { nil } // hash function, input [T] , output u32
|
||||
// hash_func fn (T) u32 = empty_cb // hash function, input [T] , output u32
|
||||
table_size int // every entry is one-bit, packed into `table`
|
||||
num_functions int // 1~16
|
||||
mut:
|
||||
table []u8
|
||||
}
|
||||
|
||||
/*
|
||||
TODO maybe allow pointing to generic fns?
|
||||
fn empty_cb[T](x T) u32 {
|
||||
panic('empty BloomFilter.hash_func callback')
|
||||
}
|
||||
*/
|
||||
|
||||
const (
|
||||
// Salt values(random values). These salts are XORed with the output of the hash function to give multiple unique hashes.
|
||||
salts = [
|
||||
|
@ -51,3 +51,14 @@ Read this section to learn how to install and connect to PostgreSQL
|
||||
[*Windows*](https://www.postgresqltutorial.com/install-postgresql);
|
||||
[*Linux*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-linux);
|
||||
[*macOS*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-macos).
|
||||
|
||||
## Using Parameterized Queries
|
||||
|
||||
Parameterized queries (exec_param, etc.) in V require the use of the following syntax: ($n).
|
||||
|
||||
The number following the $ specifies which parameter from the argument array to use.
|
||||
|
||||
```v ignore
|
||||
db.exec_param_many('INSERT INTO users (username, password) VALUES ($1, $2)', ['tom', 'securePassword']) or { panic(err) }
|
||||
db.exec_param('SELECT * FROM users WHERE username = ($1) limit 1', 'tom') or { panic(err) }
|
||||
```
|
||||
|
@ -251,7 +251,7 @@ pub fn (db DB) exec_one(query string) !Row {
|
||||
return row
|
||||
}
|
||||
|
||||
// exec_param_many executes a query with the provided parameters
|
||||
// exec_param_many executes a query with the parameters provided as ($1), ($2), ($n)
|
||||
pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
|
||||
unsafe {
|
||||
mut param_vals := []&char{len: params.len}
|
||||
@ -265,12 +265,12 @@ pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
|
||||
}
|
||||
}
|
||||
|
||||
// exec_param2 executes a query with 1 parameter, and returns either an error on failure, or the full result set on success
|
||||
// exec_param2 executes a query with 1 parameter ($1), and returns either an error on failure, or the full result set on success
|
||||
pub fn (db DB) exec_param(query string, param string) ![]Row {
|
||||
return db.exec_param_many(query, [param])
|
||||
}
|
||||
|
||||
// exec_param2 executes a query with 2 parameters, and returns either an error on failure, or the full result set on success
|
||||
// exec_param2 executes a query with 2 parameters ($1) and ($2), and returns either an error on failure, or the full result set on success
|
||||
pub fn (db DB) exec_param2(query string, param string, param2 string) ![]Row {
|
||||
return db.exec_param_many(query, [param, param2])
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ mut:
|
||||
|
||||
struct EventHandler[T] {
|
||||
name T
|
||||
handler EventHandlerFn
|
||||
handler EventHandlerFn = unsafe { nil }
|
||||
receiver voidptr = unsafe { nil }
|
||||
once bool
|
||||
}
|
||||
|
@ -6,15 +6,15 @@ pub struct C.FONSparams {
|
||||
flags char
|
||||
userPtr voidptr
|
||||
// int (*renderCreate)(void* uptr, int width, int height)
|
||||
renderCreate fn (uptr voidptr, width int, height int) int
|
||||
renderCreate fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||
// int (*renderResize)(void* uptr, int width, int height)
|
||||
renderResize fn (uptr voidptr, width int, height int) int
|
||||
renderResize fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||
// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
|
||||
renderUpdate fn (uptr voidptr, rect &int, data &u8)
|
||||
renderUpdate fn (uptr voidptr, rect &int, data &u8) = unsafe { nil }
|
||||
// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
|
||||
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int)
|
||||
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) = unsafe { nil }
|
||||
// void (*renderDelete)(void* uptr)
|
||||
renderDelete fn (uptr voidptr)
|
||||
renderDelete fn (uptr voidptr) = unsafe { nil }
|
||||
}
|
||||
|
||||
pub struct C.FONSquad {
|
||||
|
@ -25,15 +25,25 @@ pub mut:
|
||||
}
|
||||
|
||||
// create_image creates an `Image` from `file`.
|
||||
pub fn (ctx &Context) create_image(file string) !Image {
|
||||
// println('\ncreate_image("$file")')
|
||||
pub fn (mut ctx Context) create_image(file string) !Image {
|
||||
if !os.exists(file) {
|
||||
$if android {
|
||||
image_data := os.read_apk_asset(file)!
|
||||
mut image := ctx.create_image_from_byte_array(image_data)!
|
||||
|
||||
image.path = file
|
||||
|
||||
return image
|
||||
} $else {
|
||||
return error('image file "${file}" not found')
|
||||
}
|
||||
}
|
||||
|
||||
$if macos {
|
||||
if ctx.native_rendering {
|
||||
// return C.darwin_create_image(file)
|
||||
mut img := C.darwin_create_image(file)
|
||||
|
||||
// println('created macos image: $img.path w=$img.width')
|
||||
// C.printf('p = %p\n', img.data)
|
||||
img.id = ctx.image_cache.len
|
||||
@ -43,6 +53,7 @@ pub fn (ctx &Context) create_image(file string) !Image {
|
||||
return img
|
||||
}
|
||||
}
|
||||
|
||||
if !gfx.is_valid() {
|
||||
// Sokol is not initialized yet, add stbi object to a queue/cache
|
||||
// ctx.image_queue << file
|
||||
|
@ -382,7 +382,7 @@ pub fn (u_ Uint256) str() string {
|
||||
}
|
||||
|
||||
// uint256_from_dec_str creates a new `unsigned.Uint256` from the given string if possible
|
||||
pub fn uint256_from_dec_str(value string) ?Uint256 {
|
||||
pub fn uint256_from_dec_str(value string) !Uint256 {
|
||||
mut res := unsigned.uint256_zero
|
||||
for b_ in value.bytes() {
|
||||
b := b_ - '0'.bytes()[0]
|
||||
|
@ -170,7 +170,12 @@ fn C.mbedtls_pk_parse_keyfile(&C.mbedtls_pk_context, &char, &char, voidptr, void
|
||||
|
||||
fn C.mbedtls_net_connect(&C.mbedtls_net_context, &u8, &u8, int) int
|
||||
|
||||
fn C.mbedtls_ssl_conf_own_cert(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_pk_context)
|
||||
fn C.mbedtls_net_bind(&C.mbedtls_net_context, voidptr, &u8, int) int
|
||||
fn C.mbedtls_net_accept(&C.mbedtls_net_context, &C.mbedtls_net_context, voidptr, int, voidptr) int
|
||||
fn C.mbedtls_ssl_session_reset(&C.mbedtls_ssl_context)
|
||||
fn C.mbedtls_ssl_conf_authmode(&C.mbedtls_ssl_config, int)
|
||||
|
||||
fn C.mbedtls_ssl_conf_own_cert(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_pk_context) int
|
||||
fn C.mbedtls_ssl_conf_authmode(&C.mbedtls_ssl_config, int)
|
||||
fn C.mbedtls_ssl_conf_ca_chain(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_x509_crl)
|
||||
fn C.mbedtls_ssl_conf_rng(&C.mbedtls_ssl_config, voidptr, &C.mbedtls_ctr_drbg_context)
|
||||
|
@ -45,6 +45,172 @@ mut:
|
||||
owns_socket bool
|
||||
}
|
||||
|
||||
// SSLListener listens on a TCP port and accepts connection secured with TLS
|
||||
pub struct SSLListener {
|
||||
saddr string
|
||||
config SSLConnectConfig
|
||||
mut:
|
||||
server_fd C.mbedtls_net_context
|
||||
ssl C.mbedtls_ssl_context
|
||||
conf C.mbedtls_ssl_config
|
||||
certs &SSLCerts = unsafe { nil }
|
||||
opened bool
|
||||
// handle int
|
||||
// duration time.Duration
|
||||
}
|
||||
|
||||
// create a new SSLListener binding to `saddr`
|
||||
pub fn new_ssl_listener(saddr string, config SSLConnectConfig) !&SSLListener {
|
||||
mut listener := &SSLListener{
|
||||
saddr: saddr
|
||||
config: config
|
||||
}
|
||||
listener.init()!
|
||||
listener.opened = true
|
||||
return listener
|
||||
}
|
||||
|
||||
// finish the listener and clean up resources
|
||||
pub fn (mut l SSLListener) shutdown() ! {
|
||||
$if trace_ssl ? {
|
||||
eprintln(@METHOD)
|
||||
}
|
||||
if unsafe { l.certs != nil } {
|
||||
C.mbedtls_x509_crt_free(&l.certs.cacert)
|
||||
C.mbedtls_x509_crt_free(&l.certs.client_cert)
|
||||
C.mbedtls_pk_free(&l.certs.client_key)
|
||||
}
|
||||
C.mbedtls_ssl_free(&l.ssl)
|
||||
C.mbedtls_ssl_config_free(&l.conf)
|
||||
if l.opened {
|
||||
C.mbedtls_net_free(&l.server_fd)
|
||||
}
|
||||
}
|
||||
|
||||
// internal function to init and bind the listener
|
||||
fn (mut l SSLListener) init() ! {
|
||||
$if trace_ssl ? {
|
||||
eprintln(@METHOD)
|
||||
}
|
||||
|
||||
lhost, lport := net.split_address(l.saddr)!
|
||||
if l.config.cert == '' || l.config.cert_key == '' {
|
||||
return error('No certificate or key provided')
|
||||
}
|
||||
if l.config.validate && l.config.verify == '' {
|
||||
return error('No root CA provided')
|
||||
}
|
||||
C.mbedtls_net_init(&l.server_fd)
|
||||
C.mbedtls_ssl_init(&l.ssl)
|
||||
C.mbedtls_ssl_config_init(&l.conf)
|
||||
l.certs = &SSLCerts{}
|
||||
C.mbedtls_x509_crt_init(&l.certs.client_cert)
|
||||
C.mbedtls_pk_init(&l.certs.client_key)
|
||||
|
||||
unsafe {
|
||||
C.mbedtls_ssl_conf_rng(&l.conf, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||
}
|
||||
|
||||
mut ret := 0
|
||||
|
||||
if l.config.in_memory_verification {
|
||||
if l.config.verify != '' {
|
||||
ret = C.mbedtls_x509_crt_parse(&l.certs.cacert, l.config.verify.str, l.config.verify.len)
|
||||
}
|
||||
if l.config.cert != '' {
|
||||
ret = C.mbedtls_x509_crt_parse(&l.certs.client_cert, l.config.cert.str, l.config.cert.len)
|
||||
}
|
||||
if l.config.cert_key != '' {
|
||||
unsafe {
|
||||
ret = C.mbedtls_pk_parse_key(&l.certs.client_key, l.config.cert_key.str,
|
||||
l.config.cert_key.len, 0, 0, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if l.config.verify != '' {
|
||||
ret = C.mbedtls_x509_crt_parse_file(&l.certs.cacert, &char(l.config.verify.str))
|
||||
}
|
||||
ret = C.mbedtls_x509_crt_parse_file(&l.certs.client_cert, &char(l.config.cert.str))
|
||||
unsafe {
|
||||
ret = C.mbedtls_pk_parse_keyfile(&l.certs.client_key, &char(l.config.cert_key.str),
|
||||
0, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||
}
|
||||
}
|
||||
|
||||
if l.config.validate {
|
||||
C.mbedtls_ssl_conf_authmode(&l.conf, C.MBEDTLS_SSL_VERIFY_REQUIRED)
|
||||
}
|
||||
|
||||
mut bind_ip := unsafe { nil }
|
||||
if lhost != '' {
|
||||
bind_ip = voidptr(lhost.str)
|
||||
}
|
||||
bind_port := lport.str()
|
||||
|
||||
ret = C.mbedtls_net_bind(&l.server_fd, bind_ip, voidptr(bind_port.str), C.MBEDTLS_NET_PROTO_TCP)
|
||||
|
||||
if ret != 0 {
|
||||
return error_with_code("can't bind to ${l.saddr}", ret)
|
||||
}
|
||||
|
||||
ret = C.mbedtls_ssl_config_defaults(&l.conf, C.MBEDTLS_SSL_IS_SERVER, C.MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
C.MBEDTLS_SSL_PRESET_DEFAULT)
|
||||
if ret != 0 {
|
||||
return error_with_code("can't to set config defaults", ret)
|
||||
}
|
||||
|
||||
C.mbedtls_ssl_conf_ca_chain(&l.conf, &l.certs.cacert, unsafe { nil })
|
||||
ret = C.mbedtls_ssl_conf_own_cert(&l.conf, &l.certs.client_cert, &l.certs.client_key)
|
||||
|
||||
if ret != 0 {
|
||||
return error_with_code("can't load certificate", ret)
|
||||
}
|
||||
|
||||
ret = C.mbedtls_ssl_setup(&l.ssl, &l.conf)
|
||||
|
||||
if ret != 0 {
|
||||
return error_with_code("can't setup ssl", ret)
|
||||
}
|
||||
}
|
||||
|
||||
// accepts a new connection and returns a SSLConn of the connected client
|
||||
pub fn (mut l SSLListener) accept() !&SSLConn {
|
||||
mut conn := &SSLConn{
|
||||
conf: l.conf
|
||||
config: l.config
|
||||
opened: true
|
||||
owns_socket: true
|
||||
}
|
||||
|
||||
// TODO: save the client's IP address somewhere (maybe add a field to SSLConn ?)
|
||||
mut ret := C.mbedtls_net_accept(&l.server_fd, &conn.server_fd, unsafe { nil }, 0,
|
||||
unsafe { nil })
|
||||
if ret != 0 {
|
||||
return error_with_code("can't accept connection", ret)
|
||||
}
|
||||
|
||||
C.mbedtls_ssl_init(&conn.ssl)
|
||||
C.mbedtls_ssl_config_init(&conn.conf)
|
||||
ret = C.mbedtls_ssl_setup(&conn.ssl, &l.conf)
|
||||
|
||||
if ret != 0 {
|
||||
return error_with_code('SSL setup failed', ret)
|
||||
}
|
||||
|
||||
C.mbedtls_ssl_set_bio(&conn.ssl, &conn.server_fd, C.mbedtls_net_send, C.mbedtls_net_recv,
|
||||
unsafe { nil })
|
||||
|
||||
ret = C.mbedtls_ssl_handshake(&conn.ssl)
|
||||
for ret != 0 {
|
||||
if ret != C.MBEDTLS_ERR_SSL_WANT_READ && ret != C.MBEDTLS_ERR_SSL_WANT_WRITE {
|
||||
return error_with_code('SSL handshake failed', ret)
|
||||
}
|
||||
ret = C.mbedtls_ssl_handshake(&conn.ssl)
|
||||
}
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
[params]
|
||||
pub struct SSLConnectConfig {
|
||||
verify string // the path to a rootca.pem file, containing trusted CA certificate(s)
|
||||
|
@ -284,20 +284,27 @@ mut:
|
||||
accept_deadline time.Time
|
||||
}
|
||||
|
||||
pub fn listen_tcp(family AddrFamily, saddr string) !&TcpListener {
|
||||
s := new_tcp_socket(family) or { return error('${err.msg()}; could not create new socket') }
|
||||
[params]
|
||||
pub struct ListenOptions {
|
||||
pub:
|
||||
dualstack bool = true
|
||||
backlog int = 128
|
||||
}
|
||||
|
||||
pub fn listen_tcp(family AddrFamily, saddr string, options ListenOptions) !&TcpListener {
|
||||
mut s := new_tcp_socket(family) or { return error('${err.msg()}; could not create new socket') }
|
||||
s.set_dualstack(options.dualstack) or {}
|
||||
|
||||
addrs := resolve_addrs(saddr, family, .tcp) or {
|
||||
return error('${err.msg()}; could not resolve address ${saddr}')
|
||||
}
|
||||
|
||||
// TODO(logic to pick here)
|
||||
addr := addrs[0]
|
||||
|
||||
// cast to the correct type
|
||||
alen := addr.len()
|
||||
socket_error_message(C.bind(s.handle, voidptr(&addr), alen), 'binding to ${saddr} failed')!
|
||||
socket_error_message(C.listen(s.handle, 128), 'listening on ${saddr} failed')!
|
||||
socket_error_message(C.listen(s.handle, options.backlog), 'listening on ${saddr} with maximum backlog pending queue of ${options.backlog}, failed')!
|
||||
return &TcpListener{
|
||||
sock: s
|
||||
accept_deadline: no_deadline
|
||||
|
@ -150,9 +150,7 @@ pub fn (mut ws Client) listen() ! {
|
||||
ws.debug_log('got message: ${msg.opcode}')
|
||||
match msg.opcode {
|
||||
.text_frame {
|
||||
log_msg = 'read: text'
|
||||
ws.debug_log(log_msg)
|
||||
unsafe { log_msg.free() }
|
||||
ws.debug_log('read: text')
|
||||
ws.send_message_event(msg)
|
||||
unsafe { msg.free() }
|
||||
}
|
||||
@ -184,9 +182,7 @@ pub fn (mut ws Client) listen() ! {
|
||||
}
|
||||
}
|
||||
.close {
|
||||
log_msg = 'read: close'
|
||||
ws.debug_log(log_msg)
|
||||
unsafe { log_msg.free() }
|
||||
ws.debug_log('read: close')
|
||||
defer {
|
||||
ws.manage_clean_close()
|
||||
}
|
||||
|
@ -13,17 +13,15 @@ pub fn input_password(prompt string) !string {
|
||||
if termios.tcgetattr(0, mut old_state) != 0 {
|
||||
return last_error()
|
||||
}
|
||||
defer {
|
||||
termios.tcsetattr(0, C.TCSANOW, mut old_state)
|
||||
println('')
|
||||
}
|
||||
|
||||
mut new_state := old_state
|
||||
|
||||
new_state.c_lflag &= termios.invert(C.ECHO) // Disable echoing of characters
|
||||
termios.tcsetattr(0, C.TCSANOW, mut new_state)
|
||||
new_state.disable_echo()
|
||||
termios.set_state(0, new_state)
|
||||
|
||||
password := input_opt(prompt) or { return error('Failed to read password') }
|
||||
|
||||
termios.set_state(0, old_state)
|
||||
|
||||
println('')
|
||||
return password
|
||||
}
|
||||
|
@ -106,8 +106,6 @@ fn (mut pv Picoev) del(fd int) int {
|
||||
}
|
||||
|
||||
if pv.update_events(fd, picoev.picoev_del) != 0 {
|
||||
target.loop_id = -1
|
||||
target.fd = 0
|
||||
return -1
|
||||
}
|
||||
|
||||
@ -149,16 +147,21 @@ fn (mut pv Picoev) set_timeout(fd int, secs int) {
|
||||
// timeout event
|
||||
[direct_array_access; inline]
|
||||
fn (mut pv Picoev) handle_timeout() {
|
||||
mut to_remove := []int{}
|
||||
|
||||
for fd, timeout in pv.timeouts {
|
||||
if timeout <= pv.loop.now {
|
||||
to_remove << fd
|
||||
}
|
||||
}
|
||||
|
||||
for fd in to_remove {
|
||||
target := pv.file_descriptors[fd]
|
||||
assert target.loop_id == pv.loop.id
|
||||
|
||||
pv.timeouts.delete(fd)
|
||||
unsafe { target.cb(fd, picoev.picoev_timeout, &pv) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// accept_callback accepts a new connection from `listen_fd` and adds it to the loop
|
||||
fn accept_callback(listen_fd int, events int, cb_arg voidptr) {
|
||||
|
@ -248,7 +248,7 @@ mut:
|
||||
// counters for quantifier check (repetitions)
|
||||
rep int
|
||||
// validator function pointer
|
||||
validator FnValidator
|
||||
validator FnValidator = unsafe { nil }
|
||||
// groups variables
|
||||
group_neg bool // negation flag for the group, 0 => no negation > 0 => negataion
|
||||
group_rep int // repetition of the group
|
||||
@ -376,7 +376,7 @@ fn (mut re RE) reset_src() {
|
||||
******************************************************************************/
|
||||
struct BslsStruct {
|
||||
ch rune // meta char
|
||||
validator FnValidator // validator function pointer
|
||||
validator FnValidator = unsafe { nil } // validator function pointer
|
||||
}
|
||||
|
||||
const (
|
||||
@ -463,7 +463,7 @@ mut:
|
||||
cc_type int // type of cc token
|
||||
ch0 rune // first char of the interval a-b a in this case
|
||||
ch1 rune // second char of the interval a-b b in this case
|
||||
validator FnValidator // validator function pointer
|
||||
validator FnValidator = unsafe { nil } // validator function pointer
|
||||
}
|
||||
|
||||
enum CharClass_parse_state {
|
||||
|
@ -6,10 +6,21 @@ pub const used_import = 1
|
||||
#flag -I @VEXEROOT/thirdparty/sokol/util
|
||||
#flag freebsd -I /usr/local/include
|
||||
#flag darwin -fobjc-arc
|
||||
|
||||
#flag linux -lX11 -lGL -lXcursor -lXi -lpthread
|
||||
#flag freebsd -L/usr/local/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag openbsd -L/usr/X11R6/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag windows -lgdi32
|
||||
|
||||
// Note that -lm is needed *only* for sokol_gl.h's usage of sqrtf(),
|
||||
// but without -lm, this fails:
|
||||
// `v -cc gcc ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||
// With tcc, this succeeds with or without -lm:
|
||||
// `v ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||
$if !tinyc {
|
||||
#flag linux -lm
|
||||
}
|
||||
|
||||
// METAL
|
||||
$if macos {
|
||||
$if darwin_sokol_glcore33 ? {
|
||||
@ -19,10 +30,6 @@ $if macos {
|
||||
#flag -framework Metal -framework Cocoa -framework MetalKit -framework QuartzCore
|
||||
}
|
||||
}
|
||||
$if linux {
|
||||
#flag -D SOKOL_GLCORE33
|
||||
}
|
||||
|
||||
$if ios {
|
||||
#flag -DSOKOL_METAL
|
||||
#flag -framework Foundation -framework Metal -framework MetalKit -framework UIKit
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sg_allocator {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sg_logger {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ pub type GLContextDesc = C.sg_gl_context_desc
|
||||
|
||||
struct C.sg_metal_context_desc {
|
||||
device voidptr
|
||||
renderpass_descriptor_cb fn () voidptr
|
||||
drawable_cb fn () voidptr
|
||||
renderpass_descriptor_cb fn () voidptr = unsafe { nil }
|
||||
drawable_cb fn () voidptr = unsafe { nil }
|
||||
}
|
||||
|
||||
pub type MetalContextDesc = C.sg_metal_context_desc
|
||||
@ -55,8 +55,8 @@ pub type MetalContextDesc = C.sg_metal_context_desc
|
||||
struct C.sg_d3d11_context_desc {
|
||||
device voidptr
|
||||
device_context voidptr
|
||||
render_target_view_cb fn () voidptr
|
||||
depth_stencil_view_cb fn () voidptr
|
||||
render_target_view_cb fn () voidptr = unsafe { nil }
|
||||
depth_stencil_view_cb fn () voidptr = unsafe { nil }
|
||||
}
|
||||
|
||||
pub type D3D11ContextDesc = C.sg_d3d11_context_desc
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sapp_allocator {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sapp_logger {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -37,18 +37,19 @@ pub type IconDesc = C.sapp_icon_desc
|
||||
[typedef]
|
||||
pub struct C.sapp_desc {
|
||||
pub:
|
||||
init_cb fn () // these are the user-provided callbacks without user data
|
||||
frame_cb fn ()
|
||||
cleanup_cb fn ()
|
||||
event_cb fn (&Event) //&sapp_event)
|
||||
fail_cb fn (&u8)
|
||||
// these are the user-provided callbacks without user data
|
||||
init_cb fn () = unsafe { nil }
|
||||
frame_cb fn () = unsafe { nil }
|
||||
cleanup_cb fn () = unsafe { nil }
|
||||
event_cb fn (&Event) = unsafe { nil } // &sapp_event
|
||||
fail_cb fn (&u8) = unsafe { nil }
|
||||
|
||||
user_data voidptr // these are the user-provided callbacks with user data
|
||||
init_userdata_cb fn (voidptr)
|
||||
frame_userdata_cb fn (voidptr)
|
||||
cleanup_userdata_cb fn (voidptr)
|
||||
event_userdata_cb fn (&Event, voidptr)
|
||||
fail_userdata_cb fn (&char, voidptr)
|
||||
init_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
frame_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
cleanup_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
event_userdata_cb fn (&Event, voidptr) = unsafe { nil }
|
||||
fail_userdata_cb fn (&char, voidptr) = unsafe { nil }
|
||||
|
||||
width int // the preferred width of the window / canvas
|
||||
height int // the preferred height of the window / canvas
|
||||
|
@ -6,8 +6,8 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sfons_allocator_t {
|
||||
pub:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sgl_allocator_t {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sgl_logger_t {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ mut:
|
||||
nxt &Subscription = unsafe { nil }
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
pub enum Direction {
|
||||
pop
|
||||
push
|
||||
}
|
||||
|
@ -24,9 +24,15 @@ mut:
|
||||
|
||||
pub type ThreadCB = fn (mut p PoolProcessor, idx int, task_id int) voidptr
|
||||
|
||||
fn empty_cb(mut p PoolProcessor, idx int, task_id int) voidptr {
|
||||
unsafe {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PoolProcessorConfig {
|
||||
maxjobs int
|
||||
callback ThreadCB
|
||||
callback ThreadCB = empty_cb
|
||||
}
|
||||
|
||||
// new_pool_processor returns a new PoolProcessor instance.
|
||||
|
@ -176,7 +176,7 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
||||
C.GetSystemTimeAsFileTime(&ft_start)
|
||||
time_end := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) +
|
||||
u64(timeout / (100 * time.nanosecond))
|
||||
mut t_ms := timeout.sys_milliseconds()
|
||||
mut t_ms := u32(timeout.sys_milliseconds())
|
||||
C.AcquireSRWLockExclusive(&sem.mtx)
|
||||
mut res := 0
|
||||
c = C.atomic_load_u32(&sem.count)
|
||||
|
@ -17,7 +17,8 @@ pub fn get_terminal_size() (int, int) {
|
||||
}
|
||||
|
||||
// clear clears current terminal screen.
|
||||
pub fn clear() {
|
||||
pub fn clear() bool {
|
||||
print('\x1b[2J')
|
||||
print('\x1b[H')
|
||||
return true
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ pub fn set_tab_title(title string) bool {
|
||||
|
||||
// clear clears current terminal screen.
|
||||
// Implementation taken from https://docs.microsoft.com/en-us/windows/console/clearing-the-screen#example-2.
|
||||
pub fn clear() {
|
||||
pub fn clear() bool {
|
||||
hconsole := C.GetStdHandle(C.STD_OUTPUT_HANDLE)
|
||||
mut csbi := C.CONSOLE_SCREEN_BUFFER_INFO{}
|
||||
mut scrollrect := C.SMALL_RECT{}
|
||||
@ -106,7 +106,7 @@ pub fn clear() {
|
||||
|
||||
// Get the number of character cells in the current buffer.
|
||||
if !C.GetConsoleScreenBufferInfo(hconsole, &csbi) {
|
||||
return
|
||||
return false
|
||||
}
|
||||
// Scroll the rectangle of the entire buffer.
|
||||
scrollrect.Left = 0
|
||||
@ -130,4 +130,5 @@ pub fn clear() {
|
||||
csbi.dwCursorPosition.Y = 0
|
||||
|
||||
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
|
||||
return true
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fn C.ioctl(fd int, request u64, arg voidptr) int
|
||||
// for the underlying C.termios structure
|
||||
[inline]
|
||||
pub fn flag(value int) TcFlag {
|
||||
return int(value)
|
||||
return TcFlag(value)
|
||||
}
|
||||
|
||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
//
|
||||
// TODO Mac version needs to be implemented
|
||||
// Will serve as more advanced input method
|
||||
// based on the work of https://github.com/AmokHuginnsson/replxx
|
||||
//
|
||||
|
||||
module termios
|
||||
|
||||
// not used but needed for function declarations
|
||||
@ -14,45 +8,68 @@ type TcFlag = int
|
||||
type Speed = int
|
||||
type Cc = u8
|
||||
|
||||
// flag provides a termios flag of the correct size
|
||||
// for the underlying C.termios structure
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn flag(value int) TcFlag {
|
||||
$compile_error('feature not available')
|
||||
}
|
||||
|
||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||
// as its length varies across platforms
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn invert(value TcFlag) TcFlag {
|
||||
$compile_error('feature not available')
|
||||
}
|
||||
|
||||
// termios definitions
|
||||
// Termios definitions
|
||||
// Linux https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
|
||||
// OpenBSD https://github.com/openbsd/src/blob/master/sys/sys/termios.h
|
||||
// FreeBSD https://web.mit.edu/freebsd/head/sys/sys/_termios.h
|
||||
// Solaris https://github.com/omniti-labs/illumos-omnios/blob/master/usr/src/uts/common/sys/termios.h
|
||||
// DragonFly https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/sys/_termios.h
|
||||
// QNX https://github.com/vocho/openqnx/blob/master/trunk/lib/c/public/termios.h
|
||||
|
||||
pub struct Termios {
|
||||
pub mut:
|
||||
c_iflag TcFlag
|
||||
c_oflag TcFlag
|
||||
c_cflag TcFlag
|
||||
c_lflag TcFlag
|
||||
c_line Cc
|
||||
c_cc [32]Cc
|
||||
c_ispeed Speed
|
||||
c_ospeed Speed
|
||||
}
|
||||
|
||||
// flag provides a termios flag of the correct size
|
||||
// for the underlying C.termios structure
|
||||
pub fn flag(value int) TcFlag {
|
||||
return TcFlag(value)
|
||||
}
|
||||
|
||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||
// as its length varies across platforms
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn invert(value TcFlag) TcFlag {
|
||||
return TcFlag(~int(value))
|
||||
}
|
||||
|
||||
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn tcgetattr(fd int, mut termios_p Termios) int {
|
||||
$compile_error('feature not available')
|
||||
pub fn tcgetattr(fd int, mut t Termios) int {
|
||||
$compile_warn('termios.tcgetattr is not implemented on the platform')
|
||||
eprintln('tcgetattr, fd: ${fd}, t: ${t}')
|
||||
return 0
|
||||
}
|
||||
|
||||
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
|
||||
$compile_error('feature not available')
|
||||
pub fn tcsetattr(fd int, optional_actions int, mut t Termios) int {
|
||||
eprintln('tcsetattr, fd: ${fd}, optional_actions: ${optional_actions}, t: ${t}')
|
||||
return 0
|
||||
}
|
||||
|
||||
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
|
||||
[inline]
|
||||
// It is only implemented for Unix like OSes
|
||||
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
$compile_error('feature not available')
|
||||
eprintln('ioctl, fd: ${fd}, request: ${request}, arg: ${arg}')
|
||||
return 0
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
eprintln('set_state, fd: ${fd} | new_state: ${new_state}')
|
||||
return 0
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(8)
|
||||
}
|
||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fn C.ioctl(fd int, request u64, arg voidptr) int
|
||||
// for the underlying C.termios structure
|
||||
[inline]
|
||||
pub fn flag(value int) TcFlag {
|
||||
return int(value)
|
||||
return TcFlag(value)
|
||||
}
|
||||
|
||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -80,3 +80,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return C.ioctl(fd, request, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
mut x := new_state
|
||||
return tcsetattr(0, C.TCSANOW, mut x)
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
t.c_lflag &= invert(C.ECHO)
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
module termios
|
||||
|
||||
fn test_termios() {
|
||||
mut original_term := Termios{}
|
||||
tcgetattr(0, mut original_term)
|
||||
println(original_term)
|
||||
|
||||
mut silent_term := original_term
|
||||
silent_term.c_lflag &= invert(C.ECHO)
|
||||
tcsetattr(0, C.TCSANOW, mut silent_term)
|
||||
|
||||
mut check_term := Termios{}
|
||||
tcgetattr(0, mut check_term)
|
||||
assert check_term.c_lflag == silent_term.c_lflag
|
||||
|
||||
tcsetattr(0, C.TCSANOW, mut orginal_term)
|
||||
|
||||
tcgetattr(0, mut check_term)
|
||||
assert check_term.c_lflag == orginal_term.c_lflag
|
||||
}
|
35
vlib/term/termios/termios_test.v
Normal file
35
vlib/term/termios/termios_test.v
Normal file
@ -0,0 +1,35 @@
|
||||
module termios
|
||||
|
||||
fn test_portable() {
|
||||
assert 123 == int(flag(123))
|
||||
o := Termios{
|
||||
c_lflag: flag(0xFFFF)
|
||||
} // assume c_lflag exists everywhere
|
||||
// dump( o.c_lflag )
|
||||
mut n := o
|
||||
n.c_lflag &= invert(1)
|
||||
// dump( n.c_lflag )
|
||||
assert n.c_lflag != o.c_lflag
|
||||
n.disable_echo() // just assume it exists, and can be called everywhere
|
||||
assert true
|
||||
}
|
||||
|
||||
[if !windows]
|
||||
fn test_termios() {
|
||||
mut original_term := Termios{}
|
||||
tcgetattr(0, mut original_term)
|
||||
println(original_term)
|
||||
|
||||
mut silent_term := original_term
|
||||
silent_term.c_lflag &= invert(C.ECHO)
|
||||
tcsetattr(0, C.TCSANOW, mut silent_term)
|
||||
|
||||
mut check_term := Termios{}
|
||||
tcgetattr(0, mut check_term)
|
||||
assert check_term.c_lflag == silent_term.c_lflag
|
||||
|
||||
tcsetattr(0, C.TCSANOW, mut original_term)
|
||||
|
||||
tcgetattr(0, mut check_term)
|
||||
assert check_term.c_lflag == original_term.c_lflag
|
||||
}
|
@ -27,6 +27,15 @@ pub fn invert(value TcFlag) TcFlag {
|
||||
}
|
||||
|
||||
pub struct Termios {
|
||||
pub mut:
|
||||
c_iflag TcFlag
|
||||
c_oflag TcFlag
|
||||
c_cflag TcFlag
|
||||
c_lflag TcFlag
|
||||
c_line Cc
|
||||
c_cc [32]Cc
|
||||
c_ispeed Speed
|
||||
c_ospeed Speed
|
||||
}
|
||||
|
||||
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||
@ -47,3 +56,13 @@ pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
|
||||
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||
pub fn set_state(fd int, new_state Termios) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// disable_echo disables echoing characters as they are typed,
|
||||
// when that Termios state is later set with termios.set_state(fd,t)
|
||||
pub fn (mut t Termios) disable_echo() {
|
||||
}
|
||||
|
@ -135,3 +135,15 @@ pub fn (t Time) strftime(fmt string) string {
|
||||
C.strftime(&buf[0], usize(sizeof(buf)), fmt_c, tm)
|
||||
return unsafe { cstring_to_vstring(&char(&buf[0])) }
|
||||
}
|
||||
|
||||
// some *nix system functions (e.g. `C.poll()`, C.epoll_wait()) accept an `int`
|
||||
// value as *timeout in milliseconds* with the special value `-1` meaning "infinite"
|
||||
pub fn (d Duration) sys_milliseconds() int {
|
||||
if d > 2147483647 * millisecond { // treat 2147483647000001 .. C.INT64_MAX as "infinite"
|
||||
return -1
|
||||
} else if d <= 0 {
|
||||
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
||||
} else {
|
||||
return int(d / millisecond)
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +88,11 @@ fn darwin_utc() Time {
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn solaris_now() Time {
|
||||
fn solaris_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn solaris_utc() Time {
|
||||
fn solaris_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
@ -6,21 +6,21 @@ fn sys_mono_now_darwin() u64 {
|
||||
}
|
||||
|
||||
// darwin_now - dummy fn to compile on all platforms/compilers
|
||||
pub fn darwin_now() Time {
|
||||
fn darwin_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// solaris_now - dummy fn to compile on all platforms/compilers
|
||||
pub fn solaris_now() Time {
|
||||
fn solaris_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// darwin_utc - dummy fn to compile on all platforms/compilers
|
||||
pub fn darwin_utc() Time {
|
||||
fn darwin_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// solaris_utc - dummy fn to compile on all platforms/compilers
|
||||
pub fn solaris_utc() Time {
|
||||
fn solaris_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
@ -95,12 +95,12 @@ fn linux_utc() Time {
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn win_now() Time {
|
||||
fn win_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn win_utc() Time {
|
||||
fn win_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
@ -125,15 +125,6 @@ pub fn (d Duration) timespec() C.timespec {
|
||||
return ts
|
||||
}
|
||||
|
||||
// zero_timespec returns the calendar time in seconds and nanoseconds of the beginning of the Unix epoch.
|
||||
pub fn zero_timespec() C.timespec {
|
||||
ts := C.timespec{
|
||||
tv_sec: 0
|
||||
tv_nsec: 0
|
||||
}
|
||||
return ts
|
||||
}
|
||||
|
||||
// sleep suspends the execution of the calling thread for a given duration (in nanoseconds).
|
||||
pub fn sleep(duration Duration) {
|
||||
mut req := C.timespec{duration / second, duration % second}
|
||||
@ -147,15 +138,3 @@ pub fn sleep(duration Duration) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// some *nix system functions (e.g. `C.poll()`, C.epoll_wait()) accept an `int`
|
||||
// value as *timeout in milliseconds* with the special value `-1` meaning "infinite"
|
||||
pub fn (d Duration) sys_milliseconds() int {
|
||||
if d > C.INT32_MAX * millisecond { // treat 2147483647000001 .. C.INT64_MAX as "infinite"
|
||||
return -1
|
||||
} else if d <= 0 {
|
||||
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
||||
} else {
|
||||
return int(d / millisecond)
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ fn solaris_utc() Time {
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn darwin_now() Time {
|
||||
fn darwin_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn darwin_utc() Time {
|
||||
fn darwin_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ fn win_utc() Time {
|
||||
}
|
||||
|
||||
// unix_time returns Unix time.
|
||||
pub fn (st SystemTime) unix_time() i64 {
|
||||
fn (st SystemTime) unix_time() i64 {
|
||||
tt := C.tm{
|
||||
tm_sec: st.second
|
||||
tm_min: st.minute
|
||||
@ -184,32 +184,32 @@ pub fn (st SystemTime) unix_time() i64 {
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn darwin_now() Time {
|
||||
fn darwin_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn linux_now() Time {
|
||||
fn linux_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn solaris_now() Time {
|
||||
fn solaris_now() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn darwin_utc() Time {
|
||||
fn darwin_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn linux_utc() Time {
|
||||
fn linux_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
// dummy to compile with all compilers
|
||||
pub fn solaris_utc() Time {
|
||||
fn solaris_utc() Time {
|
||||
return Time{}
|
||||
}
|
||||
|
||||
@ -223,15 +223,3 @@ pub struct C.timeval {
|
||||
pub fn sleep(duration Duration) {
|
||||
C.Sleep(int(duration / millisecond))
|
||||
}
|
||||
|
||||
// some Windows system functions (e.g. `C.WaitForSingleObject()`) accept an `u32`
|
||||
// value as *timeout in milliseconds* with the special value `u32(-1)` meaning "infinite"
|
||||
pub fn (d Duration) sys_milliseconds() u32 {
|
||||
if d >= u32(-1) * millisecond { // treat 4294967295000000 .. C.INT64_MAX as "infinite"
|
||||
return u32(-1)
|
||||
} else if d <= 0 {
|
||||
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
||||
} else {
|
||||
return u32(d / millisecond)
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub interface Modifier {
|
||||
pub type InspectorFn = fn (value &ast.Value, data voidptr) !
|
||||
|
||||
struct Inspector {
|
||||
inspector_callback InspectorFn
|
||||
inspector_callback InspectorFn = unsafe { nil }
|
||||
mut:
|
||||
data voidptr
|
||||
}
|
||||
|
@ -381,6 +381,7 @@ pub:
|
||||
language Language
|
||||
is_union bool
|
||||
attrs []Attr
|
||||
pre_comments []Comment
|
||||
end_comments []Comment
|
||||
embeds []Embed
|
||||
pub mut:
|
||||
@ -535,6 +536,7 @@ pub:
|
||||
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
|
||||
no_body bool // just a definition `fn C.malloc()`
|
||||
is_builtin bool // this function is defined in builtin/strconv
|
||||
name_pos token.Pos
|
||||
body_pos token.Pos // function bodys position
|
||||
file string
|
||||
generic_names []string
|
||||
@ -634,6 +636,7 @@ pub:
|
||||
is_hidden bool // interface first arg
|
||||
pub mut:
|
||||
typ Type
|
||||
comments []Comment
|
||||
}
|
||||
|
||||
pub fn (p &Param) specifier() string {
|
||||
@ -1194,6 +1197,7 @@ pub:
|
||||
val_var string
|
||||
is_range bool
|
||||
pos token.Pos
|
||||
kv_pos token.Pos
|
||||
comments []Comment
|
||||
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
|
||||
// and the array cannot be indexed inside the loop
|
||||
|
@ -59,7 +59,7 @@ pub fn (node &CallExpr) fkey() string {
|
||||
}
|
||||
|
||||
// These methods are used only by vfmt, vdoc, and for debugging.
|
||||
pub fn (node &AnonFn) stringify_anon_decl(t &Table, cur_mod string, m2a map[string]string) string {
|
||||
pub fn (t &Table) stringify_anon_decl(node &AnonFn, cur_mod string, m2a map[string]string) string {
|
||||
mut f := strings.new_builder(30)
|
||||
f.write_string('fn ')
|
||||
if node.inherited_vars.len > 0 {
|
||||
@ -79,11 +79,11 @@ pub fn (node &AnonFn) stringify_anon_decl(t &Table, cur_mod string, m2a map[stri
|
||||
}
|
||||
f.write_string('] ')
|
||||
}
|
||||
stringify_fn_after_name(node.decl, mut f, t, cur_mod, m2a)
|
||||
t.stringify_fn_after_name(node.decl, mut f, cur_mod, m2a)
|
||||
return f.str()
|
||||
}
|
||||
|
||||
pub fn (node &FnDecl) stringify_fn_decl(t &Table, cur_mod string, m2a map[string]string) string {
|
||||
pub fn (t &Table) stringify_fn_decl(node &FnDecl, cur_mod string, m2a map[string]string) string {
|
||||
mut f := strings.new_builder(30)
|
||||
if node.is_pub {
|
||||
f.write_string('pub ')
|
||||
@ -120,11 +120,11 @@ pub fn (node &FnDecl) stringify_fn_decl(t &Table, cur_mod string, m2a map[string
|
||||
if name in ['+', '-', '*', '/', '%', '<', '>', '==', '!=', '>=', '<='] {
|
||||
f.write_string(' ')
|
||||
}
|
||||
stringify_fn_after_name(node, mut f, t, cur_mod, m2a)
|
||||
t.stringify_fn_after_name(node, mut f, cur_mod, m2a)
|
||||
return f.str()
|
||||
}
|
||||
|
||||
fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mod string, m2a map[string]string) {
|
||||
fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_mod string, m2a map[string]string) {
|
||||
mut add_para_types := true
|
||||
if node.generic_names.len > 0 {
|
||||
if node.is_method {
|
||||
@ -149,27 +149,26 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
||||
}
|
||||
}
|
||||
f.write_string('(')
|
||||
for i, arg in node.params {
|
||||
for i, param in node.params {
|
||||
// skip receiver
|
||||
// if (node.is_method || node.is_interface) && i == 0 {
|
||||
if node.is_method && i == 0 {
|
||||
continue
|
||||
}
|
||||
if arg.is_hidden {
|
||||
if param.is_hidden {
|
||||
continue
|
||||
}
|
||||
is_last_arg := i == node.params.len - 1
|
||||
is_type_only := arg.name == ''
|
||||
should_add_type := true // is_last_arg || is_type_only || node.params[i + 1].typ != arg.typ ||
|
||||
is_last_param := i == node.params.len - 1
|
||||
is_type_only := param.name == ''
|
||||
should_add_type := true // is_last_param || is_type_only || node.params[i + 1].typ != param.typ ||
|
||||
// (node.is_variadic && i == node.params.len - 2)
|
||||
if arg.is_mut {
|
||||
f.write_string(arg.typ.share().str() + ' ')
|
||||
if param.is_mut {
|
||||
f.write_string(param.typ.share().str() + ' ')
|
||||
}
|
||||
f.write_string(arg.name)
|
||||
arg_sym := t.sym(arg.typ)
|
||||
if arg_sym.kind == .struct_ && (arg_sym.info as Struct).is_anon {
|
||||
f.write_string(param.name)
|
||||
param_sym := t.sym(param.typ)
|
||||
if param_sym.kind == .struct_ && (param_sym.info as Struct).is_anon {
|
||||
f.write_string(' struct {')
|
||||
struct_ := arg_sym.info as Struct
|
||||
struct_ := param_sym.info as Struct
|
||||
for field in struct_.fields {
|
||||
f.write_string(' ${field.name} ${t.type_to_str(field.typ)}')
|
||||
if field.has_default_expr {
|
||||
@ -181,9 +180,9 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
||||
}
|
||||
f.write_string('}')
|
||||
} else {
|
||||
mut s := t.type_to_str(arg.typ.clear_flag(.shared_f))
|
||||
if arg.is_mut {
|
||||
if s.starts_with('&') && ((!arg_sym.is_number() && arg_sym.kind != .bool)
|
||||
mut s := t.type_to_str(param.typ.clear_flag(.shared_f))
|
||||
if param.is_mut {
|
||||
if s.starts_with('&') && ((!param_sym.is_number() && param_sym.kind != .bool)
|
||||
|| node.language != .v) {
|
||||
s = s[1..]
|
||||
}
|
||||
@ -194,13 +193,13 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
||||
if !is_type_only {
|
||||
f.write_string(' ')
|
||||
}
|
||||
if node.is_variadic && is_last_arg {
|
||||
if node.is_variadic && is_last_param {
|
||||
f.write_string('...')
|
||||
}
|
||||
f.write_string(s)
|
||||
}
|
||||
}
|
||||
if !is_last_arg {
|
||||
if !is_last_param {
|
||||
f.write_string(', ')
|
||||
}
|
||||
}
|
||||
@ -218,7 +217,7 @@ struct StringifyModReplacement {
|
||||
weight int
|
||||
}
|
||||
|
||||
fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
|
||||
pub fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
|
||||
if m2a.len == 0 || -1 == input.index_u8(`.`) {
|
||||
// a simple typename, like `string` or `[]bool`; no module aliasings apply,
|
||||
// (or there just are not any mappings)
|
||||
|
@ -10,8 +10,12 @@ mut:
|
||||
|
||||
pub type InspectorFn = fn (node &ast.Node, data voidptr) bool
|
||||
|
||||
fn empty_callback(node &ast.Node, data voidptr) bool {
|
||||
panic('empty ast.walker')
|
||||
}
|
||||
|
||||
struct Inspector {
|
||||
inspector_callback InspectorFn
|
||||
inspector_callback InspectorFn = empty_callback
|
||||
mut:
|
||||
data voidptr
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ pub fn (mut b Builder) print_warnings_and_errors() {
|
||||
for stmt in file.stmts {
|
||||
if stmt is ast.FnDecl {
|
||||
if stmt.name == fn_name {
|
||||
fheader := stmt.stringify_fn_decl(b.table, 'main', map[string]string{})
|
||||
fheader := b.table.stringify_fn_decl(&stmt, 'main', map[string]string{})
|
||||
redefines << FunctionRedefinition{
|
||||
fpath: file.path
|
||||
fline: stmt.pos.line_nr
|
||||
|
@ -777,7 +777,7 @@ fn (mut b Builder) cc_linux_cross() {
|
||||
verror(res.output)
|
||||
return
|
||||
}
|
||||
println(out_name + ' has been successfully compiled')
|
||||
println(out_name + ' has been successfully cross compiled for linux.')
|
||||
}
|
||||
|
||||
fn (mut c Builder) cc_windows_cross() {
|
||||
@ -795,10 +795,9 @@ fn (mut c Builder) cc_windows_cross() {
|
||||
if !c.pref.out_name.to_lower().ends_with('.exe') {
|
||||
c.pref.out_name += '.exe'
|
||||
}
|
||||
c.pref.out_name = os.quoted_path(c.pref.out_name)
|
||||
mut args := []string{}
|
||||
args << '${c.pref.cflags}'
|
||||
args << '-o ${c.pref.out_name}'
|
||||
args << '-o ${os.quoted_path(c.pref.out_name)}'
|
||||
args << '-w -L.'
|
||||
//
|
||||
cflags := c.get_os_cflags()
|
||||
@ -839,21 +838,6 @@ fn (mut c Builder) cc_windows_cross() {
|
||||
} else {
|
||||
args << cflags.c_options_after_target()
|
||||
}
|
||||
/*
|
||||
winroot := '${pref.default_module_path}/winroot'
|
||||
if !os.is_dir(winroot) {
|
||||
winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip'
|
||||
println('"$winroot" not found.')
|
||||
println('Download it from $winroot_url and save it in ${pref.default_module_path}')
|
||||
println('Unzip it afterwards.\n')
|
||||
println('winroot.zip contains all library and header files needed ' + 'to cross-compile for Windows.')
|
||||
exit(1)
|
||||
}
|
||||
mut obj_name := c.out_name
|
||||
obj_name = obj_name.replace('.exe', '')
|
||||
obj_name = obj_name.replace('.o.o', '.o')
|
||||
include := '-I $winroot/include '
|
||||
*/
|
||||
if os.user_os() !in ['macos', 'linux', 'termux'] {
|
||||
println(os.user_os())
|
||||
panic('your platform is not supported yet')
|
||||
@ -883,20 +867,7 @@ fn (mut c Builder) cc_windows_cross() {
|
||||
}
|
||||
exit(1)
|
||||
}
|
||||
/*
|
||||
if c.pref.build_mode != .build_module {
|
||||
link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' + '$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' + '$winroot/lib/uuid.lib'
|
||||
if c.pref.show_cc {
|
||||
println(link_cmd)
|
||||
}
|
||||
if os.system(link_cmd) != 0 {
|
||||
println('Cross compilation for Windows failed. Make sure you have lld linker installed.')
|
||||
exit(1)
|
||||
}
|
||||
// os.rm(obj_name)
|
||||
}
|
||||
*/
|
||||
println(c.pref.out_name + ' has been successfully compiled')
|
||||
println(c.pref.out_name + ' has been successfully cross compiled for windows.')
|
||||
}
|
||||
|
||||
fn (mut b Builder) build_thirdparty_obj_files() {
|
||||
|
@ -173,7 +173,7 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if expected.has_flag(.generic) {
|
||||
if expected.has_flag(.generic) && !got.has_flag(.generic) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@ -74,6 +74,9 @@ pub mut:
|
||||
inside_ct_attr bool // true inside `[if expr]`
|
||||
inside_x_is_type bool // true inside the Type expression of `if x is Type {`
|
||||
inside_comptime_for_field bool
|
||||
inside_generic_struct_init bool
|
||||
cur_struct_generic_types []ast.Type
|
||||
cur_struct_concrete_types []ast.Type
|
||||
skip_flags bool // should `#flag` and `#include` be skipped
|
||||
fn_level int // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
|
||||
smartcast_mut_pos token.Pos // match mut foo, if mut foo is Foo
|
||||
@ -2438,13 +2441,21 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
|
||||
}
|
||||
|
||||
fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
|
||||
if typ.has_flag(.generic) && c.table.cur_fn != unsafe { nil } {
|
||||
if typ.has_flag(.generic) {
|
||||
if c.inside_generic_struct_init {
|
||||
generic_names := c.cur_struct_generic_types.map(c.table.sym(it).name)
|
||||
if t_typ := c.table.resolve_generic_to_concrete(typ, generic_names, c.cur_struct_concrete_types) {
|
||||
return t_typ
|
||||
}
|
||||
}
|
||||
if c.table.cur_fn != unsafe { nil } {
|
||||
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
|
||||
c.table.cur_concrete_types)
|
||||
{
|
||||
return t_typ
|
||||
}
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
@ -3329,9 +3340,11 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||
if func := c.table.find_fn(node.name) {
|
||||
if func.generic_names.len > 0 {
|
||||
concrete_types := node.concrete_types.map(c.unwrap_generic(it))
|
||||
if concrete_types.all(!it.has_flag(.generic)) {
|
||||
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
||||
}
|
||||
}
|
||||
}
|
||||
return info.typ
|
||||
} else if node.kind == .unresolved {
|
||||
// first use
|
||||
@ -3493,9 +3506,11 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||
concrete_types)
|
||||
{
|
||||
fn_type = typ_
|
||||
if concrete_types.all(!it.has_flag(.generic)) {
|
||||
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
||||
}
|
||||
}
|
||||
}
|
||||
node.name = name
|
||||
node.kind = .function
|
||||
node.info = ast.IdentFn{
|
||||
|
@ -1654,6 +1654,26 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||
}
|
||||
node.return_type = left_sym.info.return_type
|
||||
return left_sym.info.return_type
|
||||
} else if final_left_sym.info is ast.ArrayFixed && method_name == 'wait' {
|
||||
elem_sym := c.table.sym(final_left_sym.info.elem_type)
|
||||
if elem_sym.kind == .thread {
|
||||
if node.args.len != 0 {
|
||||
c.error('`.wait()` does not have any arguments', node.args[0].pos)
|
||||
}
|
||||
thread_ret_type := c.unwrap_generic(elem_sym.thread_info().return_type)
|
||||
if thread_ret_type.has_flag(.option) {
|
||||
c.error('`.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.',
|
||||
node.pos)
|
||||
} else if thread_ret_type.has_flag(.result) {
|
||||
c.error('`.wait()` cannot be called for an array when thread functions return results. Iterate over the arrays elements instead and handle each returned result with `or`.',
|
||||
node.pos)
|
||||
}
|
||||
node.return_type = c.table.find_or_register_array(thread_ret_type)
|
||||
return node.return_type
|
||||
} else {
|
||||
c.error('`${left_sym.name}` has no method `wait()` (only thread handles and arrays of them have)',
|
||||
node.left.pos())
|
||||
}
|
||||
} else if left_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' {
|
||||
c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead',
|
||||
node.left.pos().extend(node.pos))
|
||||
@ -2304,7 +2324,7 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) !
|
||||
has_decompose := node.args.filter(it.expr is ast.ArrayDecompose).len > 0
|
||||
if has_decompose {
|
||||
// if call(...args) is present
|
||||
min_required_params = nr_args
|
||||
min_required_params = nr_args - 1
|
||||
}
|
||||
}
|
||||
if min_required_params < 0 {
|
||||
|
@ -70,6 +70,19 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do not allow uninitialized `fn` fields, or force `?fn`
|
||||
// (allow them in `C.` structs)
|
||||
if !c.is_builtin_mod && node.language == .v {
|
||||
sym := c.table.sym(field.typ)
|
||||
if sym.kind == .function {
|
||||
if !field.typ.has_flag(.option) && !field.has_default_expr
|
||||
&& field.attrs.filter(it.name == 'required').len == 0 {
|
||||
error_msg := 'uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)'
|
||||
c.note(error_msg, field.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if field.has_default_expr {
|
||||
c.expected_type = field.typ
|
||||
field.default_expr_typ = c.expr(mut field.default_expr)
|
||||
@ -155,6 +168,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
true)
|
||||
}
|
||||
}
|
||||
} else if c.table.final_sym(field.typ).kind == .function
|
||||
&& field.default_expr_typ.is_pointer() {
|
||||
continue
|
||||
} else {
|
||||
c.error('incompatible initializer for field `${field.name}`: ${err.msg()}',
|
||||
field.default_expr.pos())
|
||||
@ -315,6 +331,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||
}
|
||||
}
|
||||
struct_sym := c.table.sym(node.typ)
|
||||
mut old_inside_generic_struct_init := false
|
||||
mut old_cur_struct_generic_types := []ast.Type{}
|
||||
mut old_cur_struct_concrete_types := []ast.Type{}
|
||||
if struct_sym.info is ast.Struct {
|
||||
// check if the generic param types have been defined
|
||||
for ct in struct_sym.info.concrete_types {
|
||||
@ -352,6 +371,20 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||
c.error('a non generic struct `${node.typ_str}` used like a generic struct',
|
||||
node.name_pos)
|
||||
}
|
||||
if struct_sym.info.generic_types.len > 0
|
||||
&& struct_sym.info.generic_types.len == struct_sym.info.concrete_types.len {
|
||||
old_inside_generic_struct_init = c.inside_generic_struct_init
|
||||
old_cur_struct_generic_types = c.cur_struct_generic_types.clone()
|
||||
old_cur_struct_concrete_types = c.cur_struct_concrete_types.clone()
|
||||
c.inside_generic_struct_init = true
|
||||
c.cur_struct_generic_types = struct_sym.info.generic_types.clone()
|
||||
c.cur_struct_concrete_types = struct_sym.info.concrete_types.clone()
|
||||
defer {
|
||||
c.inside_generic_struct_init = old_inside_generic_struct_init
|
||||
c.cur_struct_generic_types = old_cur_struct_generic_types
|
||||
c.cur_struct_concrete_types = old_cur_struct_concrete_types
|
||||
}
|
||||
}
|
||||
} else if struct_sym.info is ast.Alias {
|
||||
parent_sym := c.table.sym(struct_sym.info.parent_type)
|
||||
// e.g. ´x := MyMapAlias{}´, should be a cast to alias type ´x := MyMapAlias(map[...]...)´
|
||||
@ -613,10 +646,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||
// and the second part is all fields embedded in the structure
|
||||
// If the return value data composition form in `c.table.struct_fields()` is modified,
|
||||
// need to modify here accordingly.
|
||||
fields := c.table.struct_fields(type_sym)
|
||||
mut fields := c.table.struct_fields(type_sym)
|
||||
mut checked_types := []ast.Type{}
|
||||
|
||||
for i, field in fields {
|
||||
for i, mut field in fields {
|
||||
if field.name in inited_fields {
|
||||
continue
|
||||
}
|
||||
@ -628,7 +661,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||
}
|
||||
if field.has_default_expr {
|
||||
if i < info.fields.len && field.default_expr_typ == 0 {
|
||||
if field.default_expr is ast.StructInit {
|
||||
if mut field.default_expr is ast.StructInit {
|
||||
idx := c.table.find_type_idx(field.default_expr.typ_str)
|
||||
if idx != 0 {
|
||||
info.fields[i].default_expr_typ = ast.new_type(idx)
|
||||
@ -637,6 +670,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||
if field.typ.is_any_kind_of_pointer() {
|
||||
info.fields[i].default_expr_typ = field.typ
|
||||
}
|
||||
} else if field.default_expr is ast.Ident
|
||||
&& field.default_expr.info is ast.IdentFn {
|
||||
c.expr(mut field.default_expr)
|
||||
} else {
|
||||
if const_field := c.table.global_scope.find_const('${field.default_expr}') {
|
||||
info.fields[i].default_expr_typ = const_field.typ
|
||||
|
@ -1,5 +1,5 @@
|
||||
struct St {
|
||||
attr fn()
|
||||
attr fn () = unsafe { nil }
|
||||
}
|
||||
|
||||
fn (s St) attr() {}
|
||||
|
@ -0,0 +1,6 @@
|
||||
vlib/v/checker/tests/fn_array_decompose_arg_mismatch_err_c.vv:2:6: error: expected 0 arguments, but got 1
|
||||
1 | fn main() {
|
||||
2 | foo(...args)
|
||||
| ~~~~~~~
|
||||
3 | }
|
||||
4 |
|
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
foo(...args)
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
vlib/v/checker/tests/fn_check_for_matching_option_result_in_fields.vv:2:2: notice: uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)
|
||||
1 | struct Abc {
|
||||
2 | f fn (voidptr)
|
||||
| ~~~~~~~~~~~~~~
|
||||
3 | }
|
||||
4 |
|
||||
vlib/v/checker/tests/fn_check_for_matching_option_result_in_fields.vv:7:3: error: cannot assign to field `f`: expected `fn (voidptr)`, not `fn (voidptr) ?`
|
||||
5 | fn main() {
|
||||
6 | a := Abc{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user