Compare commits

...

4 Commits

Author SHA1 Message Date
Delyan Angelov 3baf1741ba
make files: add a `make check` target, that runs `v test-all` locally
ci/woodpecker/push/vc Pipeline was successful Details
ci/woodpecker/push/docker Pipeline was successful Details
ci/woodpecker/push/arch Pipeline was successful Details
2022-05-01 19:25:53 +02:00
David 'Epper' Marshall bf954cc9bc
time: relative update (#14240) 2022-05-01 19:25:52 +02:00
Daniel Däschle d75469965e
cgen: fix unsafe return error (#14233) 2022-05-01 19:25:52 +02:00
playX 924e2e65fe
checker: allow pointer index for translated code (#14231) 2022-05-01 19:25:52 +02:00
9 changed files with 190 additions and 64 deletions

View File

@ -76,7 +76,7 @@ endif
endif
endif
.PHONY: all clean fresh_vc fresh_tcc check_for_working_tcc
.PHONY: all clean check fresh_vc fresh_tcc check_for_working_tcc
ifdef prod
VFLAGS+=-prod
@ -164,3 +164,5 @@ selfcompile-static:
install:
@echo 'Please use `sudo ./v symlink` instead.'
check:
$(V) test-all

View File

@ -3,6 +3,8 @@ VFLAGS ?=
CFLAGS ?=
LDFLAGS ?=
.PHONY: all check
all:
rm -rf vc/
git clone --depth 1 --quiet https://git.rustybever.be/Chewing_Bever/vc
@ -12,3 +14,6 @@ all:
rm -rf v1 v2 vc/
@echo "V has been successfully built"
./v run ./cmd/tools/detect_tcc.v
check:
./v test-all

View File

@ -39,7 +39,7 @@ if !shift_counter! LSS 1 (
if "%~1" == "help" (
if not ["%~2"] == [""] set "subcmd=%~2"& shift& set /a shift_counter+=1
)
for %%z in (build clean cleanall help) do (
for %%z in (build clean cleanall check help) do (
if "%~1" == "%%z" set target=%1& shift& set /a shift_counter+=1& goto :verifyopt
)
)
@ -67,6 +67,12 @@ exit /b 2
:init
goto :!target!
:check
echo.
echo Check everything
v.exe test-all
exit /b 0
:cleanall
call :clean
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
@ -259,10 +265,11 @@ echo Compiler:
echo -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang Set C compiler
echo.
echo Target:
echo build[default] Compiles V using the given C compiler
echo clean Clean build artifacts and debugging symbols
echo cleanall Cleanup entire ALL build artifacts and vc repository
echo help Display usage help for the given target
echo build[default] Compiles V using the given C compiler
echo clean Clean build artifacts and debugging symbols
echo cleanall Cleanup entire ALL build artifacts and vc repository
echo check Check that tests pass, and the repository is in a good shape for Pull Requests
echo help Display help for the given target
echo.
echo Examples:
echo make.bat -msvc
@ -304,8 +311,8 @@ echo Compiler:
echo -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang Set C compiler
echo.
echo Options:
echo --local Use the local vc repository without
echo syncing with remote
echo --local Use the local vc repository without
echo syncing with remote
exit /b 0
:bootstrap_tcc

View File

@ -87,48 +87,53 @@ const tokens_4 = ['MMMM', 'DDDD', 'DDDo', 'dddd', 'YYYY']
// custom_format returns a date with custom format
//
// | | Token | Output |
// | :----------- | -------: | :--------- |
// | Month | M | 1 2 ... 11 12 |
// | ----------: | :------ | :--------- |
// | **Month** | M | 1 2 ... 11 12 |
// | | Mo | 1st 2nd ... 11th 12th |
// | | MM | 01 02 ... 11 12 |
// | | MMM | Jan Feb ... Nov Dec |
// | | MMMM | January February ... November December |
// | Quarter | Q | 1 2 3 4 |
// | **Quarter** | Q | 1 2 3 4 |
// | | QQ | 01 02 03 04 |
// | | Qo | 1st 2nd 3rd 4th |
// | Day of Month | D | 1 2 ... 30 31 |
// | **Day of Month** | D | 1 2 ... 30 31 |
// | | Do | 1st 2nd ... 30th 31st |
// | | DD | 01 02 ... 30 31 |
// | Day of Year | DDD | 1 2 ... 364 365 |
// | **Day of Year** | DDD | 1 2 ... 364 365 |
// | | DDDo | 1st 2nd ... 364th 365th |
// | | DDDD | 001 002 ... 364 365 |
// | Day of Week | d | 0 1 ... 5 6 (Sun-Sat) |
// | **Day of Week** | d | 0 1 ... 5 6 (Sun-Sat) |
// | | c | 1 2 ... 6 7 (Mon-Sun) |
// | | dd | Su Mo ... Fr Sa |
// | | ddd | Sun Mon ... Fri Sat |
// | | dddd | Sunday Monday ... Friday Saturday |
// | Week of Year | w | 1 2 ... 52 53 |
// | **Week of Year** | w | 1 2 ... 52 53 |
// | | wo | 1st 2nd ... 52nd 53rd |
// | | ww | 01 02 ... 52 53 |
// | Year | YY | 70 71 ... 29 30 |
// | **Year** | YY | 70 71 ... 29 30 |
// | | YYYY | 1970 1971 ... 2029 2030 |
// | Era | N | BC AD |
// | **Era** | N | BC AD |
// | | NN | Before Christ, Anno Domini |
// | AM/PM | A | AM PM |
// | **AM/PM** | A | AM PM |
// | | a | am pm |
// | Hour | H | 0 1 ... 22 23 |
// | **Hour** | H | 0 1 ... 22 23 |
// | | HH | 00 01 ... 22 23 |
// | | h | 1 2 ... 11 12 |
// | | hh | 01 02 ... 11 12 |
// | | k | 1 2 ... 23 24 |
// | | kk | 01 02 ... 23 24 |
// | Minute | m | 0 1 ... 58 59 |
// | **Minute** | m | 0 1 ... 58 59 |
// | | mm | 00 01 ... 58 59 |
// | Second | s | 0 1 ... 58 59 |
// | **Second** | s | 0 1 ... 58 59 |
// | | ss | 00 01 ... 58 59 |
// | Offset | Z | -7 -6 ... +5 +6 |
// | **Offset** | Z | -7 -6 ... +5 +6 |
// | | ZZ | -0700 -0600 ... +0500 +0600 |
// | | ZZZ | -07:00 -06:00 ... +05:00 +06:00 |
//
// Usage:
// ```v
// println(time.now().custom_format('MMMM Mo YY N kk:mm:ss A')) // output like: January 1st 22 AD 13:45:33 PM
// ```
pub fn (t Time) custom_format(s string) string {
mut tokens := []string{}
for i := 0; i < s.len; {

View File

@ -0,0 +1,58 @@
import time
fn test_relative() {
// past
mut date := time.now()
assert date.relative() == 'now'
date = date.add_seconds(-61)
assert date.relative() == '1 minute ago'
assert date.relative_short() == '1m ago'
date = date.add_seconds(-120)
assert date.relative() == '3 minutes ago'
assert date.relative_short() == '3m ago'
date = date.add_seconds(-1 * time.seconds_per_hour)
assert date.relative() == '1 hour ago'
assert date.relative_short() == '1h ago'
date = date.add_seconds(-5 * time.seconds_per_hour)
assert date.relative() == '6 hours ago'
assert date.relative_short() == '6h ago'
date = date.add_seconds(-1 * time.seconds_per_day)
assert date.relative() == '1 day ago'
assert date.relative_short() == '1d ago'
date = date.add_seconds(-4 * time.seconds_per_day)
assert date.relative() == '5 days ago'
assert date.relative_short() == '5d ago'
date = time.now().add_seconds(-75 * time.seconds_per_day)
assert date.relative() == 'last ${date.custom_format('MMM')} ${date.custom_format('D')}'
assert date.relative_short() == '75d ago'
date = time.now().add_seconds(-400 * time.seconds_per_day)
assert date.relative() == '1 year ago'
assert date.relative_short() == '1y ago'
// future
date = time.now()
date = date.add_seconds(61)
assert date.relative() == 'in 1 minute'
assert date.relative_short() == 'in 1m'
date = date.add_seconds(120)
assert date.relative() == 'in 3 minutes'
assert date.relative_short() == 'in 3m'
date = date.add_seconds(1 * time.seconds_per_hour)
assert date.relative() == 'in 1 hour'
assert date.relative_short() == 'in 1h'
date = date.add_seconds(5 * time.seconds_per_hour)
assert date.relative() == 'in 6 hours'
assert date.relative_short() == 'in 6h'
date = date.add_seconds(time.seconds_per_day)
assert date.relative() == 'in 1 day'
assert date.relative_short() == 'in 1d'
date = date.add_seconds(4 * time.seconds_per_day)
assert date.relative() == 'in 5 days'
assert date.relative_short() == 'in 5d'
date = time.now().add_seconds(75 * time.seconds_per_day)
assert date.relative() == 'on ${date.custom_format('MMM')} ${date.custom_format('D')}'
assert date.relative_short() == 'in 75d'
date = time.now().add_seconds(400 * time.seconds_per_day)
assert date.relative() == 'in 1 year'
assert date.relative_short() == 'in 1y'
}

View File

@ -131,48 +131,70 @@ pub fn since(t Time) Duration {
// relative returns a string representation of the difference between t
// and the current time.
//
// Sample outputs:
// ```
// // future
// now
// in 5 minutes
// in 1 day
// on Feb 17
// // past
// 2 hours ago
// last Jan 15
// 5 years ago
// ```
pub fn (t Time) relative() string {
znow := now()
secs := znow.unix - t.unix
if secs <= 30 {
// right now or in the future
// TODO handle time in the future
mut secs := znow.unix - t.unix
mut prefix := ''
mut suffix := ''
if secs < 0 {
secs *= -1
prefix = 'in '
} else {
suffix = ' ago'
}
if secs < time.seconds_per_minute / 2 {
return 'now'
}
if secs < 60 {
return '1m'
}
if secs < 3600 {
m := secs / 60
if secs < time.seconds_per_hour {
m := secs / time.seconds_per_minute
if m == 1 {
return '1 minute ago'
return '${prefix}1 minute$suffix'
}
return '$m minutes ago'
return '$prefix$m minutes$suffix'
}
if secs < 3600 * 24 {
h := secs / 3600
if secs < time.seconds_per_hour * 24 {
h := secs / time.seconds_per_hour
if h == 1 {
return '1 hour ago'
return '${prefix}1 hour$suffix'
}
return '$h hours ago'
return '$prefix$h hours$suffix'
}
if secs < 3600 * 24 * 5 {
d := secs / 3600 / 24
if secs < time.seconds_per_hour * 24 * 7 {
d := secs / time.seconds_per_hour / 24
if d == 1 {
return '1 day ago'
return '${prefix}1 day$suffix'
}
return '$d days ago'
return '$prefix$d days$suffix'
}
if secs > 3600 * 24 * 10000 {
return ''
if secs < time.seconds_per_hour * 24 * 365 {
if prefix == 'in ' {
return 'on $t.md()'
}
return 'last $t.md()'
}
return t.md()
y := secs / time.seconds_per_hour / 24 / 365
if y == 1 {
return '${prefix}1 year$suffix'
}
return '$prefix$y years$suffix'
}
// relative_short returns a string saying how long ago a time occured as follows:
// 0-30 seconds: `"now"`; 30-60 seconds: `"1m"`; anything else is rounded to the
// nearest minute, hour or day; anything higher than 10000 days (about 27 years)
// years returns an empty string.
// nearest minute, hour, day, or year
// Some Examples:
// `0s -> 'now'`;
// `20s -> 'now'`;
@ -184,28 +206,44 @@ pub fn (t Time) relative() string {
// `15842354871s -> ''`
pub fn (t Time) relative_short() string {
znow := now()
secs := znow.unix - t.unix
if secs <= 30 {
// right now or in the future
// TODO handle time in the future
mut secs := znow.unix - t.unix
mut prefix := ''
mut suffix := ''
if secs < 0 {
secs *= -1
prefix = 'in '
} else {
suffix = ' ago'
}
if secs < time.seconds_per_minute / 2 {
return 'now'
}
if secs < 60 {
return '1m'
if secs < time.seconds_per_hour {
m := secs / time.seconds_per_minute
if m == 1 {
return '${prefix}1m$suffix'
}
return '$prefix${m}m$suffix'
}
if secs < 3600 {
return '${secs / 60}m'
if secs < time.seconds_per_hour * 24 {
h := secs / time.seconds_per_hour
if h == 1 {
return '${prefix}1h$suffix'
}
return '$prefix${h}h$suffix'
}
if secs < 3600 * 24 {
return '${secs / 3600}h'
if secs < time.seconds_per_hour * 24 * 365 {
d := secs / time.seconds_per_hour / 24
if d == 1 {
return '${prefix}1d$suffix'
}
return '$prefix${d}d$suffix'
}
if secs < 3600 * 24 * 5 {
return '${secs / 3600 / 24}d'
y := secs / time.seconds_per_hour / 24 / 365
if y == 1 {
return '${prefix}1y$suffix'
}
if secs > 3600 * 24 * 10000 {
return ''
}
return t.md()
return '$prefix${y}y$suffix'
}
// day_of_week returns the current day of a given year, month, and day,

View File

@ -3809,7 +3809,8 @@ fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_ty
if typ_sym.kind in [.array, .array_fixed, .string] {
if !(index_type.is_int() || index_type_sym.kind == .enum_
|| (index_type_sym.kind == .alias
&& (index_type_sym.info as ast.Alias).parent_type.is_int())) {
&& (index_type_sym.info as ast.Alias).parent_type.is_int())
|| (c.pref.translated && index_type.is_any_kind_of_pointer())) {
type_str := if typ_sym.kind == .string {
'non-integer string index `$index_type_sym.name`'
} else {

View File

@ -5181,7 +5181,7 @@ fn c_name(name_ string) string {
fn (mut g Gen) type_default(typ_ ast.Type) string {
typ := g.unwrap_generic(typ_)
if typ.has_flag(.optional) {
if typ.has_flag(.optional) || typ.has_flag(.result) {
return '{0}'
}
// Always set pointers to 0

View File

@ -63,3 +63,13 @@ fn util_error_propagation() ! {
fn test_return_on_error_propagation() {
util_error_propagation() or { assert err.msg() == 'abc' }
}
fn unsafe_return_error() !int {
unsafe {
return error('abc')
}
}
fn test_unsafe_return_error() {
unsafe_return_error() or { assert err.msg() == 'abc' }
}