all: support `mut volatile x := 123` declarations (#11940)

pull/11946/head
Delyan Angelov 2021-09-22 13:06:30 +03:00 committed by GitHub
parent 76e360ce86
commit bf2569a9a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 47 additions and 6 deletions

View File

@ -5530,6 +5530,7 @@ type
typeof
union
unsafe
volatile
__offsetof
```
See also [V Types](#v-types).

View File

@ -703,6 +703,7 @@ pub mut:
typ Type
is_mut bool
is_static bool
is_volatile bool
is_optional bool
share ShareType
}
@ -996,6 +997,7 @@ pub mut:
left_types []Type
right_types []Type
is_static bool // for translated code only
is_volatile bool // for disabling variable access optimisations (needed for hardware drivers)
is_simple bool // `x+=2` in `for x:=1; ; x+=2`
has_cross_var bool
}

View File

@ -1719,6 +1719,9 @@ pub fn (mut f Fmt) ident(node ast.Ident) {
if var_info.is_static {
f.write('static ')
}
if var_info.is_volatile {
f.write('volatile ')
}
}
f.write_language_prefix(node.language)
if node.name == 'it' && f.it_name != '' && !f.inside_lambda { // allow `it` in lambdas

View File

@ -2374,6 +2374,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if assign_stmt.is_static {
g.write('static ')
}
if assign_stmt.is_volatile {
g.write('volatile ')
}
mut return_type := ast.void_type
is_decl := assign_stmt.op == .decl_assign
g.assign_op = assign_stmt.op

View File

@ -0,0 +1,2 @@
volatile int *zzz = HEAP(int, (123));
volatile int* pzzz = &(*(zzz));

View File

@ -0,0 +1,2 @@
123
&123

View File

@ -0,0 +1,4 @@
mut volatile zzz := 123
mut volatile pzzz := &zzz
println(zzz)
println(&int(voidptr(pzzz)))

View File

@ -156,6 +156,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
}
}
mut is_static := false
mut is_volatile := false
for i, lx in left {
match mut lx {
ast.Ident {
@ -174,6 +175,9 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
}
is_static = true
}
if iv.is_volatile {
is_volatile = true
}
}
r0 := right[0]
mut v := ast.Var{
@ -232,5 +236,6 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
has_cross_var: has_cross_var
is_simple: p.inside_for && p.tok.kind == .lcbr
is_static: is_static
is_volatile: is_volatile
}
}

View File

@ -32,7 +32,7 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr {
}
// Prefix
match p.tok.kind {
.key_mut, .key_shared, .key_atomic, .key_static {
.key_mut, .key_shared, .key_atomic, .key_static, .key_volatile {
ident := p.parse_ident(ast.Language.v)
node = ident
if p.inside_defer {

View File

@ -865,7 +865,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
mut arch := pref.arch_from_string(p.tok.lit) or { pref.Arch._auto }
mut is_volatile := false
mut is_goto := false
if p.tok.lit == 'volatile' && p.tok.kind == .name {
if p.tok.kind == .key_volatile {
arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto }
is_volatile = true
p.next()
@ -1820,6 +1820,10 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
if is_static {
p.next()
}
is_volatile := p.tok.kind == .key_volatile
if is_volatile {
p.next()
}
if p.tok.kind != .name {
p.error('unexpected token `$p.tok.lit`')
return ast.Ident{
@ -1838,6 +1842,7 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
info: ast.IdentVar{
is_mut: false
is_static: false
is_volatile: false
}
scope: p.scope
}
@ -1861,6 +1866,7 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
info: ast.IdentVar{
is_mut: is_mut
is_static: is_static
is_volatile: is_volatile
share: ast.sharetype_from_flags(is_shared, is_atomic)
}
scope: p.scope

View File

@ -60,7 +60,6 @@ struct ReservedKeywords {
typedef int
unsigned int
void int
volatile int
while int
}
@ -120,18 +119,16 @@ fn test_at() {
fn test_reserved_keywords() {
// Make sure we can initialize them correctly using full syntax.
rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
// Test a few as it'll take too long to test all. If it's initialized
// correctly, other fields are also probably valid.
assert rk_holder.unix == 5
assert rk_holder.while == 3
rk_holder2 := ReservedKeywords{
inline: 9
volatile: 11
}
// Make sure partial initialization works too.
assert rk_holder2.inline == 9
assert rk_holder2.volatile == 11
assert rk_holder2.while == 0 // Zero value as not specified.
}

View File

@ -0,0 +1,14 @@
fn test_volatile_var() {
mut volatile zzz := 123
assert zzz == 123
}
fn test_volatile_pointer() {
x := 123
y := 456
mut volatile p := unsafe { &x }
println(p)
p = unsafe { &y }
println(p)
assert unsafe { *p == y }
}

View File

@ -126,6 +126,7 @@ pub enum Kind {
key_union
key_pub
key_static
key_volatile
key_unsafe
keyword_end
_end_
@ -303,6 +304,7 @@ fn build_token_str() []string {
s[Kind.key_global] = '__global'
s[Kind.key_union] = 'union'
s[Kind.key_static] = 'static'
s[Kind.key_volatile] = 'volatile'
s[Kind.key_as] = 'as'
s[Kind.key_defer] = 'defer'
s[Kind.key_match] = 'match'