1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check incorrect names

This commit is contained in:
Enzo Baldisserri 2020-05-16 16:12:23 +02:00 committed by GitHub
parent 3bd88a3cc2
commit f44a40eee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 636 additions and 597 deletions

View File

@ -213,7 +213,7 @@ fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
fn C.SetHandleInformation(hObject voidptr, dwMask u32, dwFlags u32) bool
fn C.SetHandleInformation(hObject voidptr, dwMask u32, dw_flags u32) bool
fn C.ExpandEnvironmentStringsW(lpSrc &u16, lpDst &u16, nSize u32) u32
@ -228,7 +228,7 @@ fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumbe
fn C.GetFileAttributesW(lpFileName byteptr) u32
fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int
fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lp_reserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int
fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int

View File

@ -31,7 +31,6 @@ fn test_float_equal_operator() {
assert a.gebit(1)
assert -1 == 1 * -1
assert -1.0 == 1.0 * -1.0
a = f64(1)
a += 0.000001
a -= 0.000001
@ -47,7 +46,6 @@ fn test_float_equal_operator() {
assert a.gtbit(f32(1))
assert a >= 1
assert a.gebit(1)
f := 1.2
ab := int(f)
assert ab == 1
@ -62,7 +60,6 @@ fn test_str_methods() {
assert int(-1).str() == '-1'
assert i64(1).str() == '1'
assert i64(-1).str() == '-1'
// assert byte(1).str() == '1'
// assert byte(-1).str() == '255'
assert u16(1).str() == '1'
@ -131,17 +128,11 @@ fn test_cmp() {
assert 1 0
}
*/
type myint int
type mystring string
type MyInt int
fn test_int_alias() {
/*
i := myint(2)
s := mystring('hi')
ss := s + '!'
i := MyInt(2)
assert i + 10 == 12
*/
}
fn test_hex() {
@ -194,49 +185,43 @@ fn test_int_decl() {
fn test_int_to_hex() {
// array hex
st := [byte(`V`),`L`,`A`,`N`,`G`]
assert st.hex() == "564c414e47"
st := [byte(`V`), `L`, `A`, `N`, `G`]
assert st.hex() == '564c414e47'
assert st.hex().len == 10
st1 := [byte(0x41)].repeat(100)
assert st1.hex() == "41".repeat(100)
//--- int to hex tests
assert st1.hex() == '41'.repeat(100)
// --- int to hex tests
c0 := 12
// 8Bit
assert byte(0).hex() == "0"
assert byte(c0).hex() == "c"
assert i8(c0).hex() == "c"
assert byte(127).hex() == "7f"
assert i8(127).hex() == "7f"
assert byte(255).hex() == "ff"
assert byte(-1).hex() == "ff"
assert byte(0).hex() == '0'
assert byte(c0).hex() == 'c'
assert i8(c0).hex() == 'c'
assert byte(127).hex() == '7f'
assert i8(127).hex() == '7f'
assert byte(255).hex() == 'ff'
assert byte(-1).hex() == 'ff'
// 16bit
assert u16(0).hex() == "0"
assert i16(c0).hex() == "c"
assert u16(c0).hex() == "c"
assert i16(32767).hex() == "7fff"
assert u16(32767).hex() == "7fff"
assert i16(-1).hex() == "ffff"
assert u16(65535).hex() == "ffff"
assert u16(0).hex() == '0'
assert i16(c0).hex() == 'c'
assert u16(c0).hex() == 'c'
assert i16(32767).hex() == '7fff'
assert u16(32767).hex() == '7fff'
assert i16(-1).hex() == 'ffff'
assert u16(65535).hex() == 'ffff'
// 32bit
assert u32(0).hex() == "0"
assert c0.hex() == "c"
assert u32(c0).hex() == "c"
assert 2147483647.hex() == "7fffffff"
assert u32(2147483647).hex() == "7fffffff"
assert (-1).hex() == "ffffffff"
assert u32(4294967295).hex() == "ffffffff"
assert u32(0).hex() == '0'
assert c0.hex() == 'c'
assert u32(c0).hex() == 'c'
assert 2147483647.hex() == '7fffffff'
assert u32(2147483647).hex() == '7fffffff'
assert (-1).hex() == 'ffffffff'
assert u32(4294967295).hex() == 'ffffffff'
// 64 bit
assert u64(0).hex() == "0"
assert i64(c0).hex() == "c"
assert u64(c0).hex() == "c"
assert i64(9223372036854775807).hex() == "7fffffffffffffff"
assert u64(9223372036854775807).hex() == "7fffffffffffffff"
assert i64(-1).hex() == "ffffffffffffffff"
assert u64(18446744073709551615).hex() == "ffffffffffffffff"
assert u64(0).hex() == '0'
assert i64(c0).hex() == 'c'
assert u64(c0).hex() == 'c'
assert i64(9223372036854775807).hex() == '7fffffffffffffff'
assert u64(9223372036854775807).hex() == '7fffffffffffffff'
assert i64(-1).hex() == 'ffffffffffffffff'
assert u64(18446744073709551615).hex() == 'ffffffffffffffff'
}

View File

@ -766,3 +766,12 @@ fn test_string_literal_with_backslash(){
Three'
assert b == 'OneTwoThree'
}
/*
type MyString string
fn test_string_alias() {
s := MyString('hi')
ss := s + '!'
}
*/

View File

@ -3,35 +3,49 @@ module clipboard
import time
struct WndClassEx {
cbSize u32
cb_size u32
style u32
lpfnWndProc voidptr
cbClsExtra int
cbWndExtra int
hInstance C.HINSTANCE
hIcon C.HICON
hCursor C.HCURSOR
hbrBackground C.HBRUSH
lpszMenuName &u16 // LPCWSTR
lpszClassName &u16
hIconSm &u16
lpfn_wnd_proc voidptr
cb_cls_extra int
cb_wnd_extra int
h_instance C.HINSTANCE
h_icon C.HICON
h_cursor C.HCURSOR
hbr_background C.HBRUSH
lpsz_menu_name &u16 // LPCWSTR
lpsz_class_name &u16
h_icon_sm &u16
}
fn C.RegisterClassEx(class WndClassEx) int
fn C.GetClipboardOwner() &C.HWND
fn C.CreateWindowEx(dwExStyle i64, lpClassName &u16, lpWindowName &u16, dwStyle i64, x int, y int, nWidth int, nHeight int, hWndParent i64, hMenu voidptr, hInstance voidptr, lpParam voidptr) &C.HWND
//fn C.MultiByteToWideChar(CodePage u32, dwFlags u16, lpMultiByteStr byteptr, cbMultiByte int, lpWideCharStr u16, cchWideChar int) int
fn C.CreateWindowEx(dwExStyle i64, lpClassName, lpWindowName &u16, dwStyle i64, x, y, nWidth, nHeight int, hWndParent i64, hMenu, h_instance, lpParam voidptr) &C.HWND
// fn C.MultiByteToWideChar(CodePage u32, dw_flags u16, lpMultiByteStr byteptr, cbMultiByte int, lpWideCharStr u16, cchWideChar int) int
fn C.EmptyClipboard()
fn C.CloseClipboard()
fn C.GlobalAlloc(uFlag u32, size i64) C.HGLOBAL
fn C.GlobalFree(buf C.HGLOBAL)
fn C.GlobalLock(buf C.HGLOBAL)
fn C.GlobalUnlock(buf C.HGLOBAL)
fn C.SetClipboardData(uFormat u32, data voidptr) C.HANDLE
fn C.GetClipboardData(uFormat u32) C.HANDLE
fn C.DefWindowProc(hwnd C.HWND, msg u32, wParam C.WPARAM, lParam C.LPARAM) C.LRESULT
fn C.SetLastError(error i64)
fn C.OpenClipboard(hwnd C.HWND) int
fn C.DestroyWindow(hwnd C.HWND)
struct Clipboard {
@ -45,7 +59,6 @@ struct Clipboard {
fn (cb &Clipboard) get_clipboard_lock() bool {
mut retries := cb.max_retries
mut last_error := u32(0)
for {
retries--
if retries < 0 {
@ -57,7 +70,6 @@ fn (cb &Clipboard) get_clipboard_lock() bool {
} else if last_error != u32(C.ERROR_ACCESS_DENIED) {
return false
}
time.sleep(cb.retry_delay)
}
C.SetLastError(last_error)
@ -65,24 +77,25 @@ fn (cb &Clipboard) get_clipboard_lock() bool {
}
fn new_clipboard() &Clipboard {
mut cb := &Clipboard {
mut cb := &Clipboard{
max_retries: 5
retry_delay: 5
}
class_name := "clipboard"
wndclass := WndClassEx {
cbSize: sizeof(WndClassEx)
lpfnWndProc: voidptr(&C.DefWindowProc)
lpszClassName: class_name.to_wide()
lpszMenuName: 0
hIconSm: 0
class_name := 'clipboard'
wndclass := WndClassEx{
cb_size: sizeof(WndClassEx)
lpfn_wnd_proc: voidptr(&C.DefWindowProc)
lpsz_class_name: class_name.to_wide()
lpsz_menu_name: 0
h_icon_sm: 0
}
if C.RegisterClassEx(&wndclass) == 0 && C.GetLastError() != u32(C.ERROR_CLASS_ALREADY_EXISTS) {
println("Failed registering class.")
println('Failed registering class.')
}
hwnd := C.CreateWindowEx(0, wndclass.lpszClassName, wndclass.lpszClassName, 0, 0, 0, 0, 0, C.HWND_MESSAGE, C.NULL, C.NULL, C.NULL)
hwnd := C.CreateWindowEx(0, wndclass.lpsz_class_name, wndclass.lpsz_class_name, 0, 0, 0,
0, 0, C.HWND_MESSAGE, C.NULL, C.NULL, C.NULL)
if hwnd == C.NULL {
println("Error creating window!")
println('Error creating window!')
}
cb.hwnd = hwnd
return cb
@ -96,21 +109,24 @@ fn (cb &Clipboard) has_ownership() bool {
return C.GetClipboardOwner() == cb.hwnd
}
fn (cb mut Clipboard) clear() {
if !cb.get_clipboard_lock() {return}
fn (mut cb Clipboard) clear() {
if !cb.get_clipboard_lock() {
return
}
C.EmptyClipboard()
C.CloseClipboard()
cb.foo = 0
}
fn (cb mut Clipboard) free(){
fn (mut cb Clipboard) free() {
C.DestroyWindow(cb.hwnd)
cb.foo = 0
}
// the string.to_wide doesn't work with SetClipboardData, don't know why
fn to_wide(text string) &C.HGLOBAL {
len_required := C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, C.NULL, 0)
len_required := C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len +
1, C.NULL, 0)
buf := C.GlobalAlloc(C.GMEM_MOVEABLE, sizeof(u16) * len_required)
if buf != C.HGLOBAL(C.NULL) {
mut locked := &u16(C.GlobalLock(buf))
@ -121,7 +137,7 @@ fn to_wide(text string) &C.HGLOBAL {
return buf
}
fn (cb mut Clipboard) set_text(text string) bool {
fn (mut cb Clipboard) set_text(text string) bool {
cb.foo = 0
buf := to_wide(text)
if !cb.get_clipboard_lock() {
@ -131,7 +147,7 @@ fn (cb mut Clipboard) set_text(text string) bool {
// EmptyClipboard must be called to properly update clipboard ownership
C.EmptyClipboard()
if C.SetClipboardData(C.CF_UNICODETEXT, buf) == C.HANDLE(C.NULL) {
println("SetClipboardData: Failed.")
println('SetClipboardData: Failed.')
C.CloseClipboard()
C.GlobalFree(buf)
return false
@ -142,15 +158,15 @@ fn (cb mut Clipboard) set_text(text string) bool {
return true
}
fn (cb mut Clipboard) get_text() string {
fn (mut cb Clipboard) get_text() string {
cb.foo = 0
if !cb.get_clipboard_lock() {
return ""
return ''
}
h_data := C.GetClipboardData(C.CF_UNICODETEXT)
if h_data == C.HANDLE(C.NULL) {
C.CloseClipboard()
return ""
return ''
}
str := string_from_wide(&u16(C.GlobalLock(h_data)))
C.GlobalUnlock(h_data)

View File

@ -164,27 +164,27 @@ fn utf8util_char_len(b byte) int {
//
// up_low make the dirt job
fn up_low(s string, upper_flag bool) string {
mut _index := 0
mut index := 0
mut str_res := malloc(s.len + 1)
for {
ch_len := utf8util_char_len(s.str[_index])
ch_len := utf8util_char_len(s.str[index])
if ch_len == 1 {
if upper_flag==true {
str_res[_index] = C.toupper(s.str[_index])
str_res[index] = C.toupper(s.str[index])
}else{
str_res[_index] = C.tolower(s.str[_index])
str_res[index] = C.tolower(s.str[index])
}
}
else if ch_len > 1 && ch_len < 5{
mut lword := 0
for i:=0; i < ch_len ; i++ {
lword = (lword << 8 ) | int( s.str[_index + i] )
lword = (lword << 8 ) | int( s.str[index + i] )
}
//C.printf(" #%d (%x) ", _index, lword)
//C.printf(" #%d (%x) ", index, lword)
mut res := 0
@ -215,7 +215,7 @@ fn up_low(s string, upper_flag bool) string {
// char not in table, no need of conversion
if ch_index == 0 {
for i in 0..ch_len {
str_res[_index + i] = s.str[_index + i]
str_res[index + i] = s.str[index + i]
}
//C.printf("\n")
}else{
@ -227,13 +227,13 @@ fn up_low(s string, upper_flag bool) string {
ch1 := byte( (tab_char >> 0) & 0x3f ) | 0x80 /*10xx xxxx*/
//C.printf("[%02x%02x] \n",ch0,ch1)
str_res[ _index + 0 ] = ch0
str_res[ _index + 1 ] = ch1
str_res[ index + 0 ] = ch0
str_res[ index + 1 ] = ch1
//****************************************************************
// BUG: doesn't compile, workaround use shitf to right of 0 bit
//****************************************************************
//str_res[_index + 1 ] = byte( tab_char & 0xbf ) /*1011 1111*/
//str_res[index + 1 ] = byte( tab_char & 0xbf ) /*1011 1111*/
}
else if ch_len == 3 {
@ -242,16 +242,16 @@ fn up_low(s string, upper_flag bool) string {
ch2 := byte( (tab_char >> 0) & 0x3f ) | 0x80 /*10xx xxxx*/
//C.printf("[%02x%02x%02x] \n",ch0,ch1,ch2)
str_res[_index + 0 ] = ch0
str_res[_index + 1 ] = ch1
str_res[_index + 2 ] = ch2
str_res[index + 0 ] = ch0
str_res[index + 1 ] = ch1
str_res[index + 2 ] = ch2
}
// TODO: write if needed
else if ch_len == 4 {
// place holder!!
// at the present time simply copy the utf8 char
for i in 0..ch_len {
str_res[_index + i] = s.str[_index + i]
str_res[index + i] = s.str[index + i]
}
}
}
@ -260,20 +260,20 @@ fn up_low(s string, upper_flag bool) string {
// other cases, just copy the string
else{
for i in 0..ch_len {
str_res[_index + i] = s.str[_index + i]
str_res[index + i] = s.str[index + i]
}
}
_index += ch_len
index += ch_len
// we are done, exit the loop
if _index >= s.len {
if index >= s.len {
break
}
}
// for c compatibility set the ending 0
str_res[_index]=0
str_res[index]=0
//C.printf("str_res: %s\n--------------\n",str_res)

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module freetype
import os
@ -9,19 +8,17 @@ import gx
import gg
import glm
import gl
/*
TODO
!!!!!!
Use a font atlas
!!!!!!
*/
#flag windows -I @VROOT/thirdparty/freetype/include
#flag windows -L @VROOT/thirdparty/freetype/win64
#flag solaris -I/opt/local/include/freetype2
#flag solaris -L/opt/local/lib
#flag darwin -I/usr/local/include/freetype2
// MacPorts
#flag darwin -I/opt/local/include/freetype2
@ -29,49 +26,39 @@ Use a font atlas
#flag freebsd -I/usr/local/include/freetype2
#flag freebsd -Wl -L/usr/local/lib
#flag -lfreetype
//#flag -I @VROOT/thirdparty/freetype
//#flag @VROOT/thirdparty/freetype/libfreetype.a
// #flag -I @VROOT/thirdparty/freetype
// #flag @VROOT/thirdparty/freetype/libfreetype.a
#flag darwin -lpng -lbz2 -lz
#flag linux -I/usr/include/freetype2
#flag linux -I.
#include "ft2build.h"
#include FT_FREETYPE_H
fn C.FT_Init_FreeType() voidptr
fn C.FT_New_Face() voidptr
fn C.FT_Set_Pixel_Sizes()
pub const (
default_font_size = 12
)
struct Character {
code i64
texture_id u32
size gg.Vec2
horizontal_bearing_px gg.Vec2
horizontal_advance_px u32
vertical_bearing_px gg.Vec2
vertical_advance_px u32
}
[typedef]
struct C.FT_Library {}
struct C.FT_Library {
}
pub struct FreeType {
shader gl.Shader
// use_ortho bool
width int
height int
vao u32
@ -125,20 +112,21 @@ struct C.FT_FaceRec {
family_name charptr
style_name charptr
}
///type FT_Face &C.FT_FaceRec
// /type FT_Face &C.FT_FaceRec
fn C.FT_Load_Char(voidptr, i64, int) int
fn ft_load_char(face &C.FT_FaceRec, code i64) Character {
//println('\nftload_char( code=$code)')
//C.printf('face=%p\n', face)
//C.printf('cobj=%p\n', _face.cobj)
ret := C.FT_Load_Char(face, code, C.FT_LOAD_RENDER|C.FT_LOAD_FORCE_AUTOHINT)
//println('ret=$ret')
// println('\nftload_char( code=$code)')
// C.printf('face=%p\n', face)
// C.printf('cobj=%p\n', _face.cobj)
ret := C.FT_Load_Char(face, code, C.FT_LOAD_RENDER | C.FT_LOAD_FORCE_AUTOHINT)
// println('ret=$ret')
if ret != 0 {
println('freetype: failed to load glyph (utf32 code=$code, ' +
'error code=$ret)')
return Character{code: code}
println('freetype: failed to load glyph (utf32 code=$code, ' + 'error code=$ret)')
return Character{
code: code
}
}
// Generate texture
mut texture := 0
@ -146,8 +134,8 @@ fn ft_load_char(face &C.FT_FaceRec, code i64) Character {
C.glBindTexture(C.GL_TEXTURE_2D, texture)
fgwidth := (*face).glyph.bitmap.width
fgrows := (*face).glyph.bitmap.rows
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RED, fgwidth, fgrows,
0, C.GL_RED, C.GL_UNSIGNED_BYTE, (*face).glyph.bitmap.buffer)
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RED, fgwidth, fgrows, 0, C.GL_RED, C.GL_UNSIGNED_BYTE,
(*face).glyph.bitmap.buffer)
// Set texture options
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_S, C.GL_CLAMP_TO_EDGE)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_T, C.GL_CLAMP_TO_EDGE)
@ -173,7 +161,9 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
scale := cfg.scale
// Can only have text in ortho mode
if !cfg.use_ortho {
return &FreeType{face:0}
return &FreeType{
face: 0
}
}
width := cfg.width * scale
height := cfg.height * scale
@ -193,7 +183,7 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
shader := gl.new_shader('text')
shader.use()
projection := glm.ortho(0, width, 0, height)// 0 at BOT
projection := glm.ortho(0, width, 0, height) // 0 at BOT
shader.set_mat4('projection', projection)
// FREETYPE
ft := C.FT_Library{}
@ -215,7 +205,9 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
eprintln('freetype: font "$font_path" does not exist')
return 0
}
face := &C.FT_FaceRec{glyph:0}
face := &C.FT_FaceRec{
glyph: 0
}
ret = int(C.FT_New_Face(ft, font_path.str, 0, &face))
if ret != 0 {
eprintln('freetype: failed to load font (error=$ret) from path: $font_path')
@ -228,7 +220,7 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
// Gen texture
// Load first 128 characters of ASCII set
mut chars := []Character{}
for c in 0..128 {
for c in 0 .. 128 {
ch := ft_load_char(face, i64(c))
// s := utf32_to_str(uint(0x043f))
// s := 'п'
@ -240,10 +232,10 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
// # ch = gg__ft_load_char(f, 0xd0bf) ; // UTF 8
chars << ch
}
//ch := Character{}
// ch := Character{}
// Configure VAO
vao := gl.gen_vertex_array()
//println('new gg text context vao=$vao')
// println('new gg text context vao=$vao')
vbo := gl.gen_buffer()
gl.bind_vao(vao)
gl.bind_buffer(C.GL_ARRAY_BUFFER, vbo)
@ -253,7 +245,7 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
// # glVertexAttribPointer(0, 4, GL_FLOAT,false, 4 * sizeof(GLf32), 0);
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
// # glBindVertexArray(0);
ctx := &FreeType {
ctx := &FreeType{
shader: shader
width: width
height: height
@ -263,21 +255,21 @@ pub fn new_context(cfg gg.Cfg) &FreeType {
chars: chars
face: face
}
//ctx.init_utf8_runes()
// ctx.init_utf8_runes()
return ctx
}
pub fn (ctx mut FreeType) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
//utext := text.ustring_tmp()
pub fn (mut ctx FreeType) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
// utext := text.ustring_tmp()
utext := text.ustring()
ctx.private_draw_text(_x, _y, utext, cfg)
}
fn (ctx mut FreeType) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
fn (mut ctx FreeType) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
ctx.private_draw_text(_x, _y, text, cfg)
}
fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
fn (mut ctx FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
/*
if utext.s.contains('on_seg') {
println('\nat(0)')
@ -295,14 +287,14 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
yoffset := if ctx.scale > 1 { 5 } else { -1 } // 5 hidpi, -1 lowdpi
// println('scale=$ctx.scale size=$cfg.size')
if cfg.align == gx.ALIGN_RIGHT {
//width := utext.len * 7
// width := utext.len * 7
width := wx
x -= width + 10
}
x *= ctx.scale
y *= ctx.scale
y += yoffset
y = f32(ctx.height) - y //invert y direction
y = f32(ctx.height) - y // invert y direction
color := cfg.color
// Activate corresponding render state
ctx.shader.use()
@ -311,25 +303,24 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
gl.bind_vao(ctx.vao)
// Iterate through all characters
// utext := text.ustring()
for i in 0..utext.len {
_rune := utext.at(i)
// println('$i => $_rune')
for i in 0 .. utext.len {
rune_ := utext.at(i)
// println('$i => $rune_')
mut ch := Character{}
mut found := false
if _rune.len == 1 {
idx := _rune[0]
if rune_.len == 1 {
idx := rune_[0]
if idx < 0 || idx >= ctx.chars.len {
println('BADE RUNE $_rune')
println('BADE RUNE $rune_')
continue
}
found = true
ch = ctx.chars[_rune[0]]
}
else if _rune.len > 1 {
ch = ctx.chars[rune_[0]]
} else if rune_.len > 1 {
// TODO O(1) use map
for j in 0..ctx.utf_runes.len {
for j in 0 .. ctx.utf_runes.len {
rune_j := ctx.utf_runes[j]
if rune_j==_rune {
if rune_j == rune_ {
ch = ctx.utf_chars[j]
found = true
break
@ -337,31 +328,30 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
}
}
// A new Unicode character. Load it and cache it.
if !found && _rune.len > 0 && _rune[0] > 32 {
//c := _rune[0]
//println('cant draw rune "$_rune" code=$c, loading')
//continue
ch = ft_load_char(ctx.face, _rune.utf32_code())
//println('done loading')
ctx.utf_runes << _rune
if !found && rune_.len > 0 && rune_[0] > 32 {
// c := rune_[0]
// println('cant draw rune "$rune_" code=$c, loading')
// continue
ch = ft_load_char(ctx.face, rune_.utf32_code())
// println('done loading')
ctx.utf_runes << rune_
ctx.utf_chars << ch
//exit(1)
// exit(1)
// continue
}
xpos := x + f32(ch.horizontal_bearing_px.x) * 1
ypos := y - f32(ch.size.y + wy - ch.horizontal_bearing_px.y) * 1
//ypos := y - wy
// ypos := y - wy
w := f32(ch.size.x) * 1
h := f32(ch.size.y) * 1
// Update VBO for each character
vertices := [
xpos, ypos + h, 0.0, 0.0 ,
xpos, ypos, 0.0, 1.0 ,
xpos + w, ypos, 1.0, 1.0 ,
xpos, ypos + h, 0.0, 0.0 ,
xpos + w, ypos, 1.0, 1.0 ,
xpos + w, ypos + h, 1.0, 0.0
]
xpos, ypos + h, 0.0, 0.0,
xpos, ypos, 0.0, 1.0,
xpos + w, ypos, 1.0, 1.0,
xpos, ypos + h, 0.0, 0.0,
xpos + w, ypos, 1.0, 1.0,
xpos + w, ypos + h, 1.0, 0.0]
// Render glyph texture over quad
C.glBindTexture(C.GL_TEXTURE_2D, ch.texture_id)
// Update content of VBO memory
@ -374,7 +364,7 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
// Stop drawing if the limit is reached
if cfg.max_width > 0 {
if x >= cfg.max_width {
//break
// break
}
}
}
@ -382,8 +372,8 @@ fn (ctx mut FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf
C.glBindTexture(C.GL_TEXTURE_2D, 0)
}
pub fn (ctx mut FreeType) draw_text_def(x, y int, text string) {
cfg := gx.TextCfg {
pub fn (mut ctx FreeType) draw_text_def(x, y int, text string) {
cfg := gx.TextCfg{
color: gx.Black
size: default_font_size
align: gx.align_left
@ -391,50 +381,49 @@ pub fn (ctx mut FreeType) draw_text_def(x, y int, text string) {
ctx.draw_text(x, y, text, cfg)
}
pub fn (ctx mut FreeType) text_width(s string) int {
pub fn (mut ctx FreeType) text_width(s string) int {
x, _ := ctx.text_size(s)
return x
}
pub fn (ctx mut FreeType) text_height(s string) int {
pub fn (mut ctx FreeType) text_height(s string) int {
_, y := ctx.text_size(s)
return y
}
pub fn (ctx mut FreeType) text_size(s string) (int, int) {
//t := time.ticks()
pub fn (mut ctx FreeType) text_size(s string) (int, int) {
// t := time.ticks()
utext := s.ustring()
mut x := u32(0)
mut maxy := u32(0)
mut _rune := ''
mut rune_ := ''
mut ch := Character{}
for i in 0..utext.len {
_rune = utext.at(i)
for i in 0 .. utext.len {
rune_ = utext.at(i)
ch = Character{}
mut found := false
if _rune.len == 1 {
idx := _rune[0]
if rune_.len == 1 {
idx := rune_[0]
if idx < 0 || idx >= ctx.chars.len {
println('BADE RUNE $_rune')
println('BADE RUNE $rune_')
continue
}
found = true
ch = ctx.chars[_rune[0]]
}
else if _rune.len > 1 {
ch = ctx.chars[rune_[0]]
} else if rune_.len > 1 {
// TODO O(1) use map
for j in 0..ctx.utf_runes.len {
for j in 0 .. ctx.utf_runes.len {
rune_j := ctx.utf_runes[j]
if rune_j==_rune {
if rune_j == rune_ {
ch = ctx.utf_chars[j]
found = true
break
}
}
}
if !found && _rune.len > 0 && _rune[0] > 32 {
ch = ft_load_char(ctx.face, _rune.utf32_code())
ctx.utf_runes << _rune
if !found && rune_.len > 0 && rune_[0] > 32 {
ch = ft_load_char(ctx.face, rune_.utf32_code())
ctx.utf_runes << rune_
ctx.utf_chars << ch
}
x += ch.horizontal_advance_px
@ -442,12 +431,12 @@ pub fn (ctx mut FreeType) text_size(s string) (int, int) {
maxy = ch.vertical_advance_px
}
}
//println('text width "$s" = ${time.ticks() - t} ms')
//scaled_x := x
//scaled_y := maxy
scaled_x := int(f64(x)/ctx.scale)
scaled_y := int(f64(maxy)/ctx.scale)
//println('text_size of "${s}" | x,y: $x,$maxy | scaled_x: ${scaled_x:3d} | scaled_y: ${scaled_y:3d} ')
// println('text width "$s" = ${time.ticks() - t} ms')
// scaled_x := x
// scaled_y := maxy
scaled_x := int(f64(x) / ctx.scale)
scaled_y := int(f64(maxy) / ctx.scale)
// println('text_size of "${s}" | x,y: $x,$maxy | scaled_x: ${scaled_x:3d} | scaled_y: ${scaled_y:3d} ')
return scaled_x, scaled_y
}
@ -456,7 +445,6 @@ pub fn (f FT_Face) str() string {
return 'FT_Face{ style_name: ${ptr_str(f.style_name)} family_name: ${ptr_str(f.family_name)} }'
}
*/
pub fn (ac []Character) str() string {
mut res := []string{}
for c in ac {

View File

@ -122,7 +122,7 @@ pub:
}
// type clickpub fn pub fn (window * GLFWwindow, button, action, mods int)
type clickpubfn fn (window voidptr, button, action, mods int)
type ClickPubFn fn (window voidptr, button, action, mods int)
/*
* TODO broken

View File

@ -1,5 +1,5 @@
/*
basic ftp module
basic ftp module
RFC-959
https://tools.ietf.org/html/rfc959
@ -15,7 +15,6 @@
dtp.close()
ftp.close()
*/
module ftp
import net
@ -45,19 +44,22 @@ fn (dtp DTP) read() []byte {
mut data := []byte{}
for {
buf, len := dtp.sock.recv(1024)
if len == 0 { break }
for i in 0..len {
if len == 0 {
break
}
for i in 0 .. len {
data << buf[i]
}
unsafe { free(buf) }
unsafe {
free(buf)
}
}
return data
}
fn (dtp DTP) close() {
dtp.sock.close() or {}
dtp.sock.close() or {
}
}
struct FTP {
@ -87,11 +89,9 @@ fn (ftp FTP) read() (int, string) {
$if debug {
println('FTP.v <<< $data')
}
if data.len < 5 {
return 0, ''
}
code := data[..3].int()
if data[3] == `-` {
for {
@ -101,21 +101,18 @@ fn (ftp FTP) read() (int, string) {
}
}
}
return code, data
}
pub fn (ftp mut FTP) connect(ip string) bool {
pub fn (mut ftp FTP) connect(ip string) bool {
sock := net.dial(ip, 21) or {
return false
}
ftp.sock = sock
code, _ := ftp.read()
if code == Connected {
return true
}
return false
}
@ -126,36 +123,34 @@ pub fn (ftp FTP) login(user, passwd string) bool {
}
return false
}
mut code, data := ftp.read()
if code == LoggedIn {
return true
}
if code != SpecifyPassword {
return false
}
ftp.write('PASS $passwd') or {
$if debug {
println('ERROR sending password')
}
return false
}
code, data = ftp.read()
// TODO Replace `data` with `_`
_ := data
if code == LoggedIn {
return true
}
return false
}
pub fn (ftp FTP) close() {
send_quit := 'QUIT\r\n'
ftp.sock.send_string(send_quit) or {}
ftp.sock.close() or {}
ftp.sock.send_string(send_quit) or {
}
ftp.sock.close() or {
}
}
pub fn (ftp FTP) pwd() string {
@ -171,7 +166,9 @@ pub fn (ftp FTP) pwd() string {
}
pub fn (ftp FTP) cd(dir string) {
ftp.write('CWD $dir') or { return }
ftp.write('CWD $dir') or {
return
}
mut code, mut data := ftp.read()
match int(code) {
denied {
@ -184,7 +181,6 @@ pub fn (ftp FTP) cd(dir string) {
}
else {}
}
$if debug {
println('CD $data')
}
@ -194,14 +190,11 @@ fn new_dtp(msg string) ?DTP {
if !is_dtp_message_valid(msg) {
return error('Bad message')
}
ip, port := get_host_ip_from_dtp_message(msg)
sock := net.dial(ip, port) or {
return error('Cannot connect to the data channel')
}
dtp := DTP {
dtp := DTP{
sock: sock
ip: ip
port: port
@ -210,16 +203,15 @@ fn new_dtp(msg string) ?DTP {
}
fn (ftp FTP) pasv() ?DTP {
ftp.write('PASV') or {}
ftp.write('PASV') or {
}
code, data := ftp.read()
$if debug {
println('pass: $data')
}
if code != PassiveMode {
return error('pasive mode not allowed')
}
dtp := new_dtp(data) or {
return error(err)
}
@ -230,8 +222,8 @@ pub fn (ftp FTP) dir() ?[]string {
dtp := ftp.pasv() or {
return error('cannot establish data connection')
}
ftp.write('LIST') or {}
ftp.write('LIST') or {
}
code, _ := ftp.read()
if code == denied {
return error('LIST denied')
@ -239,23 +231,20 @@ pub fn (ftp FTP) dir() ?[]string {
if code != OpenDataConnection {
return error('data channel empty')
}
list_dir := dtp.read()
result, _ := ftp.read()
if result != CloseDataConnection {
println('LIST not ok')
}
dtp.close()
mut dir := []string{}
sdir := string(byteptr(list_dir.data))
for lfile in sdir.split('\n') {
if lfile.len >1 {
if lfile.len > 1 {
spl := lfile.split(' ')
dir << spl[spl.len-1]
dir << spl[spl.len - 1]
}
}
return dir
}
@ -263,21 +252,17 @@ pub fn (ftp FTP) get(file string) ?[]byte {
dtp := ftp.pasv() or {
return error('Cannot stablish data connection')
}
ftp.write('RETR $file') or {}
ftp.write('RETR $file') or {
}
code, _ := ftp.read()
if code == denied {
return error('Permission denied')
}
if code != OpenDataConnection {
return error('Data connection not ready')
}
blob := dtp.read()
dtp.close()
return blob
}
@ -290,7 +275,6 @@ fn is_dtp_message_valid(msg string) bool {
fn get_host_ip_from_dtp_message(msg string) (string, int) {
mut par_start_idx := -1
mut par_end_idx := -1
for i, c in msg {
if c == `(` {
par_start_idx = i + 1
@ -299,9 +283,7 @@ fn get_host_ip_from_dtp_message(msg string) (string, int) {
}
}
data := msg[par_start_idx..par_end_idx].split(',')
ip := data[0..4].join('.')
port := data[4].int() * 256 + data[5].int()
return ip, port
}

View File

@ -57,11 +57,11 @@ pub fn read_set_cookies(h map[string][]string) []&Cookie {
continue
}
name := keyval[0]
_value := keyval[1]
raw_value := keyval[1]
if !is_cookie_name_valid(name) {
continue
}
value := parse_cookie_value(_value, true) or {
value := parse_cookie_value(raw_value, true) or {
continue
}
mut c := &Cookie{
@ -75,14 +75,14 @@ pub fn read_set_cookies(h map[string][]string) []&Cookie {
continue
}
mut attr := parts[i]
mut _val := ''
mut raw_val := ''
if attr.contains('=') {
pieces := attr.split('=')
attr = pieces[0]
_val = pieces[1]
raw_val = pieces[1]
}
lower_attr := attr.to_lower()
val := parse_cookie_value(_val, false) or {
val := parse_cookie_value(raw_val, false) or {
c.unparsed << parts[i]
continue
}
@ -158,9 +158,9 @@ pub fn read_cookies(h map[string][]string, filter string) []&Cookie {
mut part := ''
for line.len > 0 {
if line.index_any(';') > 0 {
_parts := line.split(';')
part = _parts[0]
line = _parts[1]
line_parts := line.split(';')
part = line_parts[0]
line = line_parts[1]
} else {
part = line
line = ''
@ -172,9 +172,9 @@ pub fn read_cookies(h map[string][]string, filter string) []&Cookie {
mut name := part
mut val := ''
if part.contains('=') {
_parts := part.split('=')
name = _parts[0]
val = _parts[1]
val_parts := part.split('=')
name = val_parts[0]
val = val_parts[1]
}
if !is_cookie_name_valid(name) {
continue
@ -182,12 +182,9 @@ pub fn read_cookies(h map[string][]string, filter string) []&Cookie {
if filter != '' && filter != name {
continue
}
// Circumvent the issue with assigning an `or` expression to an existing value
// TODO: Fix when fixed in compiler
_val := parse_cookie_value(val, true) or {
val = parse_cookie_value(val, true) or {
continue
}
val = _val
cookies << &Cookie{name: name, value: val}
}
}

View File

@ -3,13 +3,14 @@
// that can be found in the LICENSE file.
module http
type downloadfn fn(written int)type download_finished_fn fn()
type DownloadFn = fn (written int)
/*
struct DownloadStruct {
mut:
stream voidptr
written int
cb downloadfn
cb DownloadFn
}
*/
fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) {
@ -23,7 +24,7 @@ fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) {
*/
}
pub fn download_file_with_progress(url, out string, cb downloadfn, cb_finished fn()) {
pub fn download_file_with_progress(url, out string, cb DownloadFn, cb_finished fn()) {
/*
curl := C.curl_easy_init()
if isnil(curl) {
@ -49,4 +50,3 @@ pub fn download_file_with_progress(url, out string, cb downloadfn, cb_finished f
fn empty() {
}

View File

@ -20,7 +20,6 @@ pub mut:
url string
user_agent string
verbose bool
//mut:
user_ptr voidptr
ws_func voidptr
}
@ -32,8 +31,8 @@ pub mut:
params map[string]string
headers map[string]string
cookies map[string]string
user_agent string//='v' QTODO
verbose bool=false
user_agent string // ='v' QTODO
verbose bool = false
}
pub struct Response {
@ -44,9 +43,9 @@ pub:
status_code int
}
pub fn new_request(method, url_, data string) ?Request{
pub fn new_request(method, url_, data string) ?Request {
url := if method == 'GET' { url_ + '?' + data } else { url_ }
//println('new req() method=$method url="$url" dta="$data"')
// println('new req() method=$method url="$url" dta="$data"')
return Request{
method: method.to_upper()
url: url
@ -147,7 +146,7 @@ pub fn url_encode_form_data(data map[string]string) string {
return pieces.join('&')
}
fn fetch_with_method(method string, url string, _config FetchConfig) ?Response {
fn fetch_with_method(method, url string, _config FetchConfig) ?Response {
mut config := _config
config.method = method
return fetch(url, config)
@ -173,21 +172,21 @@ fn build_url_from_fetch(_url string, config FetchConfig) ?string {
return url.str()
}
fn (req mut Request) free() {
fn (mut req Request) free() {
req.headers.free()
}
fn (resp mut Response) free() {
fn (mut resp Response) free() {
resp.headers.free()
}
// add_header adds the key and value of an HTTP request header
pub fn (req mut Request) add_header(key, val string) {
pub fn (mut req Request) add_header(key, val string) {
req.headers[key] = val
}
pub fn parse_headers(lines []string) map[string]string {
mut headers := map[string]string
mut headers := map[string]string{}
for i, line in lines {
if i == 0 {
continue
@ -258,8 +257,7 @@ fn (req &Request) method_and_url_to_response(method string, url urllib.URL) ?Res
return error(err)
}
return res
}
else if scheme == 'http' {
} else if scheme == 'http' {
// println('http_do( $nport, $method, $host_name, $path )')
res := req.http_do(nport, method, host_name, path) or {
return error(err)
@ -271,9 +269,9 @@ fn (req &Request) method_and_url_to_response(method string, url urllib.URL) ?Res
fn parse_response(resp string) Response {
// TODO: Header data type
mut headers := map[string]string
mut headers := map[string]string{}
// TODO: Cookie data type
mut cookies := map[string]string
mut cookies := map[string]string{}
first_header := resp.all_before('\n')
mut status_code := 0
if first_header.contains('HTTP/') {
@ -341,7 +339,8 @@ fn (req &Request) build_request_headers(method, host_name, path string) string {
uheaders << '${key}: ${val}\r\n'
}
uheaders << req.build_request_cookies_header()
return '$method $path HTTP/1.1\r\n' + uheaders.join('') + 'Connection: close\r\n\r\n' + req.data
return '$method $path HTTP/1.1\r\n' + uheaders.join('') + 'Connection: close\r\n\r\n' +
req.data
}
fn (req &Request) build_request_cookies_header() string {
@ -373,5 +372,3 @@ pub fn unescape(s string) string {
pub fn escape(s string) string {
panic('http.escape() was replaced with http.escape_url()')
}
type wsfn fn(s string, ptr voidptr)

View File

@ -6,7 +6,7 @@ pub struct Socket {
pub:
sockfd int
family int
_type int
typ int
proto int
}
@ -39,53 +39,39 @@ struct C.sockaddr_storage {
fn C.socket() int
fn C.setsockopt() int
fn C.htonl() int
fn C.htons() int
fn C.bind() int
fn C.listen() int
fn C.accept() int
fn C.getaddrinfo() int
fn C.connect() int
fn C.send() int
fn C.recv() int
fn C.read() int
fn C.shutdown() int
fn C.close() int
fn C.ntohs() int
fn C.getsockname() int
// create socket
pub fn new_socket(family int, _type int, proto int) ?Socket {
sockfd := C.socket(family, _type, proto)
pub fn new_socket(family, typ, proto int) ?Socket {
sockfd := C.socket(family, typ, proto)
one := 1
// This is needed so that there are no problems with reusing the
// same port after the application exits.
@ -96,7 +82,7 @@ pub fn new_socket(family int, _type int, proto int) ?Socket {
s := Socket{
sockfd: sockfd
family: family
_type: _type
typ: typ
proto: proto
}
return s
@ -107,7 +93,7 @@ pub fn socket_udp() ?Socket {
}
// set socket options
pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int {
pub fn (s Socket) setsockopt(level, optname int, optvalue &int) ?int {
res := C.setsockopt(s.sockfd, level, optname, optvalue, sizeof(&int))
if res < 0 {
return error('net.setsocketopt: failed with $res')
@ -117,8 +103,7 @@ pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int {
// bind socket to port
pub fn (s Socket) bind(port int) ?int {
mut addr := C.sockaddr_in{
}
mut addr := C.sockaddr_in{}
addr.sin_family = s.family
addr.sin_port = C.htons(port)
addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY)
@ -178,8 +163,7 @@ pub fn (s Socket) accept() ?Socket {
$if debug {
println('accept()')
}
addr := C.sockaddr_storage{
}
addr := C.sockaddr_storage{}
size := 128 // sizeof(sockaddr_storage)
sockfd := C.accept(s.sockfd, &addr, &size)
if sockfd < 0 {
@ -188,7 +172,7 @@ pub fn (s Socket) accept() ?Socket {
c := Socket{
sockfd: sockfd
family: s.family
_type: s._type
typ: s.typ
proto: s.proto
}
return c
@ -196,10 +180,9 @@ pub fn (s Socket) accept() ?Socket {
// connect to given addrress and port
pub fn (s Socket) connect(address string, port int) ?int {
mut hints := C.addrinfo{
}
mut hints := C.addrinfo{}
hints.ai_family = s.family
hints.ai_socktype = s._type
hints.ai_socktype = s.typ
hints.ai_flags = C.AI_PASSIVE
hints.ai_protocol = s.proto
hints.ai_addrlen = 0
@ -210,12 +193,12 @@ pub fn (s Socket) connect(address string, port int) ?int {
sport := '$port'
info_res := C.getaddrinfo(address.str, sport.str, &hints, &info)
if info_res != 0 {
error_message := os.get_error_msg(net.error_code())
error_message := os.get_error_msg(error_code())
return error('net.connect: getaddrinfo failed "$error_message"')
}
res := C.connect(s.sockfd, info.ai_addr, info.ai_addrlen)
if res < 0 {
error_message := os.get_error_msg(net.error_code())
error_message := os.get_error_msg(error_code())
return error('net.connect: connect failed "$error_message"')
}
return res
@ -256,11 +239,13 @@ pub fn (s Socket) send_string(sdata string) ?int {
}
// receive string data from socket. NB: you are responsible for freeing the returned byteptr
pub fn (s Socket) recv(bufsize int) (byteptr,int) {
pub fn (s Socket) recv(bufsize int) (byteptr, int) {
mut buf := byteptr(0)
unsafe { buf = malloc(bufsize) }
unsafe {
buf = malloc(bufsize)
}
res := C.recv(s.sockfd, buf, bufsize, 0)
return buf,res
return buf, res
}
// TODO: remove cread/2 and crecv/2 when the Go net interface is done
@ -304,6 +289,7 @@ pub const (
MAX_READ = 400
MSG_PEEK = 0x02
)
// write - write a string with CRLF after it over the socket s
pub fn (s Socket) write(str string) ?int {
line := '$str$CRLF'
@ -329,7 +315,7 @@ pub fn (s Socket) read_line() string {
}
buf[n] = `\0`
mut eol_idx := -1
for i in 0..n {
for i in 0 .. n {
if int(buf[i]) == `\n` {
eol_idx = i
// Ensure that tos_clone(buf) later,
@ -377,8 +363,7 @@ pub fn (s Socket) read_all() string {
}
pub fn (s Socket) get_port() int {
mut addr := C.sockaddr_in{
}
mut addr := C.sockaddr_in{}
size := 16 // sizeof(sockaddr_in)
C.getsockname(s.sockfd, &addr, &size)
return C.ntohs(addr.sin_port)

View File

@ -148,9 +148,9 @@ fn C.CopyFile(&u32, &u32, int) int
// TODO implement actual cp for linux
pub fn cp(old, new string) ?bool {
$if windows {
_old := old.replace('/', '\\')
_new := new.replace('/', '\\')
C.CopyFile(_old.to_wide(), _new.to_wide(), false)
w_old := old.replace('/', '\\')
w_new := new.replace('/', '\\')
C.CopyFile(w_old.to_wide(), w_new.to_wide(), false)
result := C.GetLastError()
if result == 0 {
return true
@ -954,8 +954,8 @@ pub fn dir_exists(path string) bool {
// is_dir returns a boolean indicating whether the given path is a directory.
pub fn is_dir(path string) bool {
$if windows {
_path := path.replace('/', '\\')
attr := C.GetFileAttributesW(_path.to_wide())
w_path := path.replace('/', '\\')
attr := C.GetFileAttributesW(w_path.to_wide())
if attr == u32(C.INVALID_FILE_ATTRIBUTES) {
return false
}

View File

@ -16,64 +16,64 @@ pub type HANDLE voidptr
// win: FILETIME
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
struct Filetime {
dwLowDateTime u32
dwHighDateTime u32
dw_low_date_time u32
dw_high_date_time u32
}
// win: WIN32_FIND_DATA
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-_win32_find_dataw
struct Win32finddata {
mut:
dwFileAttributes u32
ftCreationTime Filetime
ftLastAccessTime Filetime
ftLastWriteTime Filetime
nFileSizeHigh u32
nFileSizeLow u32
dwReserved0 u32
dwReserved1 u32
cFileName [260]u16 // MAX_PATH = 260
cAlternateFileName [14]u16 // 14
dwFileType u32
dwCreatorType u32
wFinderFlags u16
dw_file_attributes u32
ft_creation_time Filetime
ft_last_access_time Filetime
ft_last_write_time Filetime
n_file_size_high u32
n_file_size_low u32
dw_reserved0 u32
dw_reserved1 u32
c_file_name [260]u16 // MAX_PATH = 260
c_alternate_file_name [14]u16 // 14
dw_file_type u32
dw_creator_type u32
w_finder_flags u16
}
struct ProcessInformation {
mut:
hProcess voidptr
hThread voidptr
dwProcessId u32
dwThreadId u32
h_process voidptr
h_thread voidptr
dw_process_id u32
dw_thread_id u32
}
struct StartupInfo {
mut:
cb u32
lpReserved &u16
lpDesktop &u16
lpTitle &u16
dwX u32
dwY u32
dwXSize u32
dwYSize u32
dwXCountChars u32
dwYCountChars u32
dwFillAttribute u32
dwFlags u32
wShowWindow u16
cbReserved2 u16
lpReserved2 byteptr
hStdInput voidptr
hStdOutput voidptr
hStdError voidptr
lp_reserved &u16
lp_desktop &u16
lp_title &u16
dw_x u32
dw_y u32
dw_x_size u32
dw_y_size u32
dw_x_count_chars u32
dw_y_count_chars u32
dw_fill_attributes u32
dw_flags u32
w_show_window u16
cb_reserved2 u16
lp_reserved2 byteptr
h_std_input voidptr
h_std_output voidptr
h_std_error voidptr
}
struct SecurityAttributes {
mut:
nLength u32
lpSecurityDescriptor voidptr
bInheritHandle bool
n_length u32
lp_security_descriptor voidptr
b_inherit_handle bool
}
fn init_os_args_wide(argc int, argv &byteptr) []string {
@ -102,12 +102,12 @@ pub fn ls(path string) ?[]string {
// NOTE:TODO: once we have a way to convert utf16 wide character to utf8
// we should use FindFirstFileW and FindNextFileW
h_find_files := C.FindFirstFile(path_files.to_wide(), voidptr(&find_file_data))
first_filename := string_from_wide(&u16(find_file_data.cFileName))
first_filename := string_from_wide(&u16(find_file_data.c_file_name))
if first_filename != '.' && first_filename != '..' {
dir_files << first_filename
}
for C.FindNextFile(h_find_files, voidptr(&find_file_data)) > 0 {
filename := string_from_wide(&u16(find_file_data.cFileName))
filename := string_from_wide(&u16(find_file_data.c_file_name))
if filename != '.' && filename != '..' {
dir_files << filename.clone()
}
@ -186,12 +186,12 @@ pub fn mkdir(path string) ?bool {
// get_file_handle retrieves the operating-system file handle that is associated with the specified file descriptor.
pub fn get_file_handle(path string) HANDLE {
mode := 'rb'
_fd := C._wfopen(path.to_wide(), mode.to_wide())
if _fd == 0 {
fd := C._wfopen(path.to_wide(), mode.to_wide())
if fd == 0 {
return HANDLE(INVALID_HANDLE_VALUE)
}
_handle := HANDLE(C._get_osfhandle(C._fileno(_fd))) // CreateFile? - hah, no -_-
return _handle
handle := HANDLE(C._get_osfhandle(C._fileno(fd))) // CreateFile? - hah, no -_-
return handle
}
// Ref - https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea
@ -205,8 +205,7 @@ pub fn get_module_filename(handle HANDLE) ?string {
status := int(C.GetModuleFileNameW(handle, voidptr(&buf), sz))
match status {
success {
_filename := string_from_wide2(buf, sz)
return _filename
return string_from_wide2(buf, sz)
}
else {
// Must handled with GetLastError and converted by FormatMessage
@ -261,11 +260,11 @@ pub fn get_error_msg(code int) string {
if code < 0 { // skip negative
return ''
}
_ptr_text := ptr_win_get_error_msg(u32(code))
if _ptr_text == 0 { // compare with null
ptr_text := ptr_win_get_error_msg(u32(code))
if ptr_text == 0 { // compare with null
return ''
}
return string_from_wide(_ptr_text)
return string_from_wide(ptr_text)
}
// exec starts the specified command, waits for it to complete, and returns its output.
@ -277,8 +276,8 @@ pub fn exec(cmd string) ?Result {
mut child_stdout_read := &u32(0)
mut child_stdout_write := &u32(0)
mut sa := SecurityAttributes {}
sa.nLength = sizeof(C.SECURITY_ATTRIBUTES)
sa.bInheritHandle = true
sa.n_length = sizeof(C.SECURITY_ATTRIBUTES)
sa.b_inherit_handle = true
create_pipe_ok := C.CreatePipe(voidptr(&child_stdout_read),
voidptr(&child_stdout_write), voidptr(&sa), 0)
@ -294,14 +293,14 @@ pub fn exec(cmd string) ?Result {
proc_info := ProcessInformation{}
start_info := StartupInfo{
lpReserved: 0
lpDesktop: 0
lpTitle: 0
lp_reserved: 0
lp_desktop: 0
lp_title: 0
cb: sizeof(C.PROCESS_INFORMATION)
hStdInput: child_stdin
hStdOutput: child_stdout_write
hStdError: child_stdout_write
dwFlags: u32(C.STARTF_USESTDHANDLES)
h_std_input: child_stdin
h_std_output: child_stdout_write
h_std_error: child_stdout_write
dw_flags: u32(C.STARTF_USESTDHANDLES)
}
command_line := [32768]u16
C.ExpandEnvironmentStringsW(cmd.to_wide(), voidptr(&command_line), 32768)
@ -325,10 +324,10 @@ pub fn exec(cmd string) ?Result {
soutput := read_data.str().trim_space()
read_data.free()
exit_code := u32(0)
C.WaitForSingleObject(proc_info.hProcess, C.INFINITE)
C.GetExitCodeProcess(proc_info.hProcess, voidptr(&exit_code))
C.CloseHandle(proc_info.hProcess)
C.CloseHandle(proc_info.hThread)
C.WaitForSingleObject(proc_info.h_process, C.INFINITE)
C.GetExitCodeProcess(proc_info.h_process, voidptr(&exit_code))
C.CloseHandle(proc_info.h_process)
C.CloseHandle(proc_info.h_thread)
return Result {
output: soutput
exit_code: int(exit_code)

View File

@ -151,15 +151,13 @@ fn process_in_thread(pool mut PoolProcessor, task_id int) {
// return *(&T(pool.items[idx]))
//}
// TODO: the below is a hack, remove it when v2 &string() casting works again
type mystring string
// get_string_item - called by the worker callback.
// It does not use generics so it does not mess up vfmt.
// TODO: remove the need for this when vfmt becomes smarter.
pub fn (pool &PoolProcessor) get_string_item(idx int) string {
// return *(&string(pool.items[idx]))
// TODO: the below is a hack, remove it when v2 casting works again
return &mystring( pool.items[idx] )
return &string( pool.items[idx] )
}
// get_int_item - called by the worker callback.

View File

@ -8,18 +8,18 @@ struct Coord {
}
struct SmallRect {
Left i16
Top i16
Right i16
Bottom i16
left i16
top i16
right i16
bottom i16
}
struct ConsoleScreenBufferInfo {
dwSize Coord
dwCursorPosition Coord
wAttributes u16
srWindow SmallRect
dwMaximumWindowSize Coord
dw_size Coord
dw_cursor_position Coord
w_attributes u16
sr_window SmallRect
dw_maximum_window_size Coord
}
fn C.GetConsoleScreenBufferInfo(handle os.HANDLE, info &ConsoleScreenBufferInfo) bool
@ -28,13 +28,11 @@ fn C.GetConsoleScreenBufferInfo(handle os.HANDLE, info &ConsoleScreenBufferInfo)
pub fn get_terminal_size() (int, int) {
if is_atty(1) > 0 && os.getenv('TERM') != 'dumb' {
info := ConsoleScreenBufferInfo{}
if C.GetConsoleScreenBufferInfo(C.GetStdHandle(C.STD_OUTPUT_HANDLE), &info) {
columns := int(info.srWindow.Right - info.srWindow.Left + 1)
rows := int(info.srWindow.Bottom - info.srWindow.Top + 1)
columns := int(info.sr_window.right - info.sr_window.left + 1)
rows := int(info.sr_window.bottom - info.sr_window.top + 1)
return columns, rows
}
}
return default_columns_size, default_rows_size
}

View File

@ -100,6 +100,7 @@ pub:
name string
path string
expr Expr
pos token.Position
is_skipped bool // module main can be skipped in single file programs
}
@ -295,6 +296,7 @@ pub:
name string
expr Expr
has_expr bool
pos token.Position
pub mut:
typ table.Type
}

View File

@ -175,15 +175,44 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
return has_main_fn
}
fn (mut c Checker) check_valid_snake_case(name, identifier string, pos token.Position) {
if name[0] == `_` {
c.error('$identifier `$name` cannot start with `_`', pos)
}
if util.contains_capital(name) {
c.error('$identifier `$name` cannot contain uppercase letters, use snake_case instead',
pos)
}
}
fn stripped_name(name string) string {
idx := name.last_index('.') or {
-1
}
return name[(idx + 1)..]
}
fn (mut c Checker) check_valid_pascal_case(name, identifier string, pos token.Position) {
stripped_name := stripped_name(name)
if !stripped_name[0].is_capital() {
c.error('$identifier `$name` must begin with capital letter', pos)
}
}
pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
match node {
ast.AliasTypeDecl {
// TODO Replace `c.file.mod.name != 'time'` by `it.is_c` once available
if c.file.mod.name != 'time' {
c.check_valid_pascal_case(it.name, 'type alias', it.pos)
}
typ_sym := c.table.get_type_symbol(it.parent_type)
if typ_sym.kind == .placeholder {
c.error("type `$typ_sym.name` doesn't exist", it.pos)
}
}
ast.FnTypeDecl {
c.check_valid_pascal_case(it.name, 'fn type', it.pos)
typ_sym := c.table.get_type_symbol(it.typ)
fn_typ_info := typ_sym.info as table.FnType
fn_info := fn_typ_info.func
@ -199,6 +228,7 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
}
}
ast.SumTypeDecl {
c.check_valid_pascal_case(it.name, 'sum type', it.pos)
for typ in it.sub_types {
typ_sym := c.table.get_type_symbol(typ)
if typ_sym.kind == .placeholder {
@ -209,8 +239,21 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
}
}
pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
c.check_valid_pascal_case(decl.name, 'interface name', decl.pos)
for method in decl.methods {
c.check_valid_snake_case(method.name, 'method name', method.pos)
}
}
pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
if !decl.is_c && !c.is_builtin_mod {
c.check_valid_pascal_case(decl.name, 'struct name', decl.pos)
}
for i, field in decl.fields {
if !decl.is_c {
c.check_valid_snake_case(field.name, 'field name', field.pos)
}
for j in 0 .. i {
if field.name == decl.fields[j].name {
c.error('field name `$field.name` duplicate', field.pos)
@ -1094,7 +1137,12 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
}
pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
c.check_valid_pascal_case(decl.name, 'enum name', decl.pos)
for i, field in decl.fields {
if util.contains_capital(field.name) {
c.error('field name `$field.name` cannot contain uppercase letters, use snake_case instead',
field.pos)
}
for j in 0 .. i {
if field.name == decl.fields[j].name {
c.error('field name `$field.name` duplicate', field.pos)
@ -1165,13 +1213,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
val_type := assign_stmt.right_types[i]
// check variable name for beginning with capital letter 'Abc'
is_decl := assign_stmt.op == .decl_assign
if is_decl && util.contains_capital(ident.name) {
c.error('variable names cannot contain uppercase letters, use snake_case instead',
ident.pos)
} else if is_decl && ident.kind != .blank_ident {
if ident.name.starts_with('__') {
c.error('variable names cannot start with `__`', ident.pos)
}
if is_decl && ident.name != '_' {
c.check_valid_snake_case(ident.name, 'variable name', ident.pos)
}
if assign_stmt.op == .decl_assign {
c.var_decl_name = ident.name
@ -1385,6 +1428,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
mut field_names := []string{}
mut field_order := []int{}
for i, field in it.fields {
// TODO Check const name once the syntax is decided
if field.name in c.const_names {
c.error('field name `$field.name` duplicate', field.pos)
}
@ -1433,6 +1477,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.check_expr_opt_call(it.expr, etype, false)
}
ast.FnDecl {
if !it.is_c && !c.is_builtin_mod {
c.check_valid_snake_case(it.name, 'function name', it.pos)
}
if it.is_method {
sym := c.table.get_type_symbol(it.receiver.typ)
if sym.kind == .interface_ {
@ -1523,7 +1570,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.stmts(it.stmts)
c.in_for_count--
}
// ast.GlobalDecl {}
ast.GlobalDecl {
c.check_valid_snake_case(it.name, 'global name', it.pos)
}
ast.GoStmt {
if !(it.call_expr is ast.CallExpr) {
c.error('expression in `go` must be a function call', it.call_expr.position())
@ -1533,19 +1582,12 @@ fn (mut c Checker) stmt(node ast.Stmt) {
// ast.HashStmt {}
ast.Import {}
ast.InterfaceDecl {
name := it.name.after('.')
if !name[0].is_capital() {
pos := token.Position{
line_nr: it.pos.line_nr
pos: it.pos.pos + 'interface'.len
len: name.len
}
c.error('interface name must begin with capital letter', pos)
}
c.interface_decl(it)
}
ast.Module {
c.mod = it.name
c.is_builtin_mod = it.name == 'builtin'
c.check_valid_snake_case(it.name, 'module name', it.pos)
}
ast.Return {
c.returns = true
@ -1865,7 +1907,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
return table.void_type
}
pub fn (mut c Checker) concat_expr(concat_expr mut ast.ConcatExpr) table.Type {
pub fn (mut c Checker) concat_expr(mut concat_expr ast.ConcatExpr) table.Type {
mut mr_types := []table.Type{}
for expr in concat_expr.vals {
mr_types << c.expr(expr)

View File

@ -6,25 +6,29 @@ fn test_all() {
vexe := os.getenv('VEXE')
vroot := os.dir(vexe)
os.chdir(vroot)
dir := 'vlib/v/checker/tests'
classic_dir := 'vlib/v/checker/tests'
classic_tests := get_tests_in_dir(classic_dir)
global_dir := '$classic_dir/globals'
global_tests := get_tests_in_dir(global_dir)
// -prod so that warns are errors
total_errors += check_path(vexe, classic_dir, '-prod', '.out', classic_tests)
total_errors += check_path(vexe, global_dir, '--enable-globals', '.out', global_tests)
total_errors += check_path(vexe, classic_dir, '--enable-globals run', '.run.out', ['globals_error.vv'])
assert total_errors == 0
}
fn get_tests_in_dir(dir string) []string {
files := os.ls(dir) or {
panic(err)
}
mut tests := files.filter(it.ends_with('.vv'))
if tests.len == 0 {
println('no compiler tests found')
assert false
}
tests.sort()
for test in tests {
// -prod so that warns are errors
total_errors += check_path(vexe, dir, test, '-prod', '.out')
}
total_errors += check_path(vexe, dir, 'globals_error.vv', '--enable-globals run', '.run.out')
assert total_errors == 0
return tests
}
fn check_path(vexe, dir, test, voptions, result_extension string) int {
fn check_path(vexe, dir, voptions, result_extension string, tests []string) int {
mut nb_fail := 0
for test in tests {
path := os.join_path(dir, test).replace('\\', '/')
program := path.replace('.vv', '.v')
print(program + ' ')
@ -48,12 +52,13 @@ fn check_path(vexe, dir, test, voptions, result_extension string) int {
println('found:')
println(found)
println('============\n')
return 1
nb_fail += 1
} else {
println(term.green('OK'))
os.rm(program)
}
return 0
}
return nb_fail
}
fn clean_line_endings(s string) string {

View File

@ -1,5 +0,0 @@
vlib/v/checker/tests/decl_underscore.v:2:2: error: variable names cannot start with `__`
1 | fn main() {
2 | __abc := 1
| ~~~~~
3 | }

View File

@ -1,3 +0,0 @@
fn main() {
__abc := 1
}

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/enum_field_name_err.v:2:5: error: field name `Green` must be all lowercase
1 | enum Color {
2 | Green
| ~~~~~
3 | yellow
4 | }

View File

@ -1,7 +0,0 @@
enum Color {
Green
yellow
}
fn main(){
println('hello')
}

View File

@ -1,5 +0,0 @@
vlib/v/checker/tests/enum_name_err.v:1:6: error: enum name `color` must begin with capital letter
1 | enum color {
| ~~~~~
2 | green
3 | yellow

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/globals/incorrect_name_global.v:1:1: error: global name `A` cannot contain uppercase letters, use snake_case instead
1 | __global A := 1
| ~~~~~~~~~~

View File

@ -0,0 +1 @@
__global A := 1

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_alias_type.v:1:1: error: type alias `integer` must begin with capital letter
1 | type integer = int
| ~~~~~~~~~~~~

View File

@ -0,0 +1 @@
type integer = int

View File

@ -0,0 +1,3 @@
const (
_my_const = 0
)

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/incorrect_name_enum.v:1:1: error: enum name `color` must begin with capital letter
1 | enum color {
| ~~~~~~~~~~
2 | green
3 | yellow

View File

@ -2,6 +2,3 @@ enum color {
green
yellow
}
fn main(){
println('hello')
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/incorrect_name_enum_field.v:2:5: error: field name `Green` cannot contain uppercase letters, use snake_case instead
1 | enum Color {
2 | Green
| ~~~~~
3 | red
4 | blue

View File

@ -0,0 +1,5 @@
enum Color {
Green
red
blue
}

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_fn_type.v:1:1: error: fn type `callback` must begin with capital letter
1 | type callback = fn ()
| ~~~~~~~~~~~~~

View File

@ -0,0 +1 @@
type callback = fn ()

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_function.v:1:1: error: function name `_my_fn` cannot start with `_`
1 | fn _my_fn() {}
| ~~~~~~~~~~~

View File

@ -0,0 +1 @@
fn _my_fn() {}

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_interface.v:1:1: error: interface name `_MyInterface` must begin with capital letter
1 | interface _MyInterface {}
| ~~~~~~~~~

View File

@ -0,0 +1 @@
interface _MyInterface {}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/incorrect_name_interface_method.v:2:5: error: method name `_speak` cannot start with `_`
1 | interface MyInterface {
2 | _speak()
| ~~~~~~~~
3 | }

View File

@ -0,0 +1,3 @@
interface MyInterface {
_speak()
}

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_module.v:1:1: error: module name `_A` cannot start with `_`
1 | module _A
| ~~~~~~~~~

View File

@ -0,0 +1 @@
module _A

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_struct.v:1:8: error: struct name `abc` must begin with capital letter
1 | struct abc {}
| ~~~

View File

@ -0,0 +1 @@
struct abc {}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/incorrect_name_struct_field.v:2:5: error: field name `_a` cannot start with `_`
1 | struct Abc {
2 | _a int
| ~~~~~~
3 | }

View File

@ -0,0 +1,3 @@
struct Abc {
_a int
}

View File

@ -0,0 +1,3 @@
vlib/v/checker/tests/incorrect_name_sum_type.v:1:1: error: sum type `integer` must begin with capital letter
1 | type integer = i8 | i16 | int | i64
| ~~~~~~~~~~~~

View File

@ -0,0 +1 @@
type integer = i8 | i16 | int | i64

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/incorrect_name_variable.v:2:2: error: variable name `_abc` cannot start with `_`
1 | fn main() {
2 | _abc := 1
| ~~~~
3 | _ := _abc
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
_abc := 1
_ := _abc
}

View File

@ -1,7 +1,6 @@
vlib/v/checker/tests/struct_field_name_duplicate_err.v:3:4: error: field name `a` duplicate
vlib/v/checker/tests/struct_field_name_duplicate_err.v:3:2: error: field name `a` duplicate
1 | struct A {
2 | a int
3 | a string
| ~~~~~~
| ~~~~~~~~
4 | }
5 | fn main(){}

View File

@ -2,4 +2,3 @@ struct A {
a int
a string
}
fn main(){}

View File

@ -1,5 +0,0 @@
vlib/v/checker/tests/struct_name.v:1:8: error: struct name `abc` must begin with capital letter
1 | struct abc {
| ~~~
2 |
3 | }

View File

@ -1,5 +0,0 @@
struct abc {
}
fn main(){}

View File

@ -468,7 +468,7 @@ pub fn (mut g Gen) writeln(s string) {
pub fn (mut g Gen) new_tmp_var() string {
g.tmp_count++
return 'tmp$g.tmp_count'
return '_t$g.tmp_count'
}
pub fn (mut g Gen) reset_tmp_count() {
@ -1860,7 +1860,6 @@ fn (mut g Gen) concat_expr(node ast.ConcatExpr) {
styp := g.typ(node.return_type)
sym := g.table.get_type_symbol(node.return_type)
is_multi := sym.kind == .multi_return
if !is_multi {
g.expr(node.vals[0])
} else {

View File

@ -297,7 +297,6 @@ fn (mut p Parser) check_js_name() string {
// last .name
name += p.tok.lit
p.next()
return name
}
@ -462,8 +461,8 @@ pub fn (mut p Parser) stmt() ast.Stmt {
}
} else if p.peek_tok.kind == .name {
p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
} else if !p.inside_if_expr && !p.inside_match_body &&
!p.inside_or_expr && p.peek_tok.kind in [.rcbr, .eof] {
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr && p.peek_tok.kind in
[.rcbr, .eof] {
p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.position())
}
epos := p.tok.position()
@ -528,7 +527,8 @@ pub fn (mut p Parser) stmt() ast.Stmt {
}
}
.key_const {
p.error_with_pos('const can only be defined at the top level (outside of functions)', p.tok.position())
p.error_with_pos('const can only be defined at the top level (outside of functions)',
p.tok.position())
}
else {
return p.parse_comma_separated()
@ -680,7 +680,7 @@ fn (mut p Parser) parse_comma_separated() ast.Stmt {
}
}
return ast.ExprStmt{
expr: ast.ConcatExpr {
expr: ast.ConcatExpr{
vals: collected
}
pos: p.tok.position()
@ -706,7 +706,7 @@ pub fn (mut p Parser) parse_ident(is_c, is_js bool) ast.Ident {
name: '_'
kind: .blank_ident
pos: pos
info: ast.IdentVar {
info: ast.IdentVar{
is_mut: false
is_static: false
}
@ -1105,8 +1105,9 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
fn (mut p Parser) module_decl() ast.Module {
mut name := 'main'
is_skipped := p.tok.kind != .key_module
mut module_pos := token.Position{}
if !is_skipped {
module_pos := p.tok.position()
module_pos = p.tok.position()
p.next()
mut pos := p.tok.position()
name = p.check_name()
@ -1121,6 +1122,7 @@ fn (mut p Parser) module_decl() ast.Module {
p.error_with_pos('`module x` can only declare one module', pos)
}
}
module_pos = module_pos.extend(pos)
}
full_mod := p.table.qualify_module(name, p.file_name)
p.mod = full_mod
@ -1128,6 +1130,7 @@ fn (mut p Parser) module_decl() ast.Module {
return ast.Module{
name: full_mod
is_skipped: is_skipped
pos: module_pos
}
}
@ -1252,7 +1255,9 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
p.mod != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals {
p.error('use `v --enable-globals ...` to enable globals')
}
start_pos := p.tok.position()
p.next()
pos := start_pos.extend(p.tok.position())
name := p.check_name()
// println(name)
typ := p.parse_type()
@ -1280,6 +1285,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
glob := ast.GlobalDecl{
name: name
typ: typ
pos: pos
has_expr: has_expr
expr: expr
}
@ -1296,9 +1302,6 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
p.check(.key_enum)
end_pos := p.tok.position()
enum_name := p.check_name()
if enum_name.len > 0 && !enum_name[0].is_capital() {
p.error_with_pos('enum name `$enum_name` must begin with capital letter', end_pos)
}
name := p.prepend_mod(enum_name)
p.check(.lcbr)
mut vals := []string{}
@ -1307,9 +1310,6 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
for p.tok.kind != .eof && p.tok.kind != .rcbr {
pos := p.tok.position()
val := p.check_name()
if !val.is_lower() {
p.error_with_pos('field name `$val` must be all lowercase', pos)
}
vals << val
mut expr := ast.Expr{}
mut has_expr := false

View File

@ -95,8 +95,9 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
is_field_mut = true
is_field_global = true
}
field_start_pos := p.tok.position()
field_name := p.check_name()
field_pos := p.tok.position()
field_pos := field_start_pos.extend(p.tok.position())
// p.warn('field $field_name')
typ := p.parse_type()
/*
@ -288,6 +289,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
// Parse methods
mut methods := []ast.FnDecl{}
for p.tok.kind != .rcbr && p.tok.kind != .eof {
method_start_pos := p.tok.position()
line_nr := p.tok.line_nr
name := p.check_name()
if util.contains_capital(name) {
@ -307,6 +309,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
file: p.file_name
return_type: table.void_type
is_pub: true
pos: method_start_pos.extend(p.prev_tok.position())
}
if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr {
method.return_type = p.parse_type()

View File

@ -1,15 +1,11 @@
// 1 line comment
/* 1 line comment */
// 1 line comment // 1 line comment
/*
multi line comment (1)
multi line comment (2)
multi line comment (3)
*/
/*
multi line comment (1)
multi line comment (1)
/*
nested comment
*/
@ -20,44 +16,43 @@ multi line comment (3)
/* /* nested comment */ */
multi line comment (2)
*/
type MyFn1 = fn (int) string
type myfn fn (int) string
type MyFn2 = fn (a int, b int) int
type myfn2 fn (a int, b int) int
type myfn3 fn (int, int)
type MyFn3 = fn (int, int)
fn myfn4(string)
fn foobar()
fn slopediv(num u32, den u32) int
fn slopediv(num, den u32) int
type f1 fn ()
type F1 = fn ()
type f2 fn (voidptr)
type F2 = fn (voidptr)
type f3 fn (voidptr, voidptr)
type F3 = fn (voidptr, voidptr)
type f4 fn (voidptr) int
type F4 = fn (voidptr) int
type f5 fn (int, int) int
type F5 = fn (int, int) int
type f6 fn (int, int)
type F6 = fn (int, int)
fn C.atoi(byteptr) int
fn foo() {
}
type actionf_v fn ()
type ActionfV = fn ()
type actionf_p1 fn (voidptr)
type ActionfP1 = fn (voidptr)
type actionf_p2 fn (voidptr, voidptr)
type ActionfP2 = fn (voidptr, voidptr)
// TODO
fn modify_array(a mut []int) {
fn modify_array(mut a []int) {
a[0] = 10
for i in 0 .. a.len {
a[i] = a[i] * 2
@ -86,7 +81,7 @@ fn test_mut_array() {
println(nums.clone())
}
fn mod_struct(user mut User) {
fn mod_struct(mut user User) {
user.age++
}
@ -101,7 +96,7 @@ fn test_mut_struct() {
assert user.age == 19
}
fn mod_ptr(buf mut byteptr) {
fn mod_ptr(mut buf byteptr) {
buf[0] = 77
}
@ -111,7 +106,6 @@ fn test_mut_ptr() {
assert buf[0] == 77
}
fn assert_in_bool_fn(v int) bool {
assert v < 3
return true
@ -121,7 +115,8 @@ fn test_assert_in_bool_fn() {
assert_in_bool_fn(2)
}
type MyFn fn (int) int
type MyFn = fn (int) int
fn test(n int) int {
return n + 1000
}
@ -129,6 +124,7 @@ fn test(n int) int {
struct MySt {
f MyFn
}
fn test_fn_type_call() {
mut arr := []MyFn{}
arr << MyFn(test)
@ -137,10 +133,12 @@ fn test_fn_type_call() {
x1 := arr[0]
x2 := x1(10)
assert x2 == 1010
st := MySt{f:test}
st := MySt{
f: test
}
assert st.f(10) == 1010
st1 := &MySt{f:test}
st1 := &MySt{
f: test
}
assert st1.f(10) == 1010
}