From dee28d998ff6583dab49a57ee4b792d9e289a18f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 30 Jan 2019 14:24:14 +0000 Subject: [PATCH] Allow for @indent for attributes that don't require any parameters; Add -ignore-unknown-attributes --- core/odin/parser/parser.odin | 46 ++++++++++++---------- core/odin/token/token.odin | 4 +- core/runtime/core.odin | 74 ++++++++++++++++++------------------ src/build_settings.cpp | 1 + src/checker.cpp | 4 +- src/main.cpp | 6 +++ src/parser.cpp | 46 +++++++++++++--------- 7 files changed, 103 insertions(+), 78 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 153c5bca0..cad15e7ec 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -774,32 +774,38 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { parse_attribute :: proc(p: ^Parser, tok: token.Token, open_kind, close_kind: token.Kind) -> ^ast.Stmt { elems: [dynamic]^ast.Expr; - open := expect_token(p, open_kind); - p.expr_level += 1; - for p.curr_tok.kind != close_kind && - p.curr_tok.kind != token.EOF { - elem: ^ast.Expr; - elem = parse_ident(p); - if p.curr_tok.kind == token.Eq { - eq := expect_token(p, token.Eq); - value := parse_value(p); - fv := ast.new(ast.Field_Value, elem.pos, value.end); - fv.field = elem; - fv.sep = eq.pos; - fv.value = value; + open, close: token.Token; - elem = fv; - } + if p.curr_tok.kind == token.Ident { + elem := parse_ident(p); append(&elems, elem); + } else { + open = expect_token(p, open_kind); + p.expr_level += 1; + for p.curr_tok.kind != close_kind && + p.curr_tok.kind != token.EOF { + elem: ^ast.Expr; + elem = parse_ident(p); + if p.curr_tok.kind == token.Eq { + eq := expect_token(p, token.Eq); + value := parse_value(p); + fv := ast.new(ast.Field_Value, elem.pos, value.end); + fv.field = elem; + fv.sep = eq.pos; + fv.value = value; - if !allow_token(p, token.Comma) { - break; + elem = fv; + } + append(&elems, elem); + + if !allow_token(p, token.Comma) { + break; + } } + p.expr_level -= 1; + close = expect_token_after(p, close_kind, "attribute"); } - p.expr_level -= 1; - close := expect_token_after(p, close_kind, "attribute"); - attribute := ast.new(ast.Attribute, tok.pos, end_pos(close)); attribute.tok = tok.kind; attribute.open = open.pos; diff --git a/core/odin/token/token.odin b/core/odin/token/token.odin index 949c9f602..a473fbc1b 100644 --- a/core/odin/token/token.odin +++ b/core/odin/token/token.odin @@ -159,9 +159,11 @@ using Kind :: enum i32 { Yield, Await, B_Keyword_End, + + COUNT, }; -tokens := [len(Kind)]string { +tokens := [Kind.COUNT]string { "Invalid", "EOF", "Comment", diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 6730621c8..9307b5589 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -344,7 +344,7 @@ __init_context :: proc "contextless" (c: ^Context) { c.logger.data = nil; } -@(builtin) +@builtin init_global_temporary_allocator :: proc(data: []byte, backup_allocator := context.allocator) { mem.scratch_allocator_init(&global_scratch_allocator_data, data, backup_allocator); } @@ -364,7 +364,7 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code -@(builtin) +@builtin copy :: proc "contextless" (dst, src: $T/[]$E) -> int { n := max(0, min(len(dst), len(src))); if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E)); @@ -373,7 +373,7 @@ copy :: proc "contextless" (dst, src: $T/[]$E) -> int { -@(builtin) +@builtin pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E { if array == nil do return E{}; assert(len(array) > 0); @@ -382,7 +382,7 @@ pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E { return res; } -@(builtin) +@builtin unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) { bounds_check_error_loc(loc, index, len(array)); n := len(array)-1; @@ -392,7 +392,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca pop(array); } -@(builtin) +@builtin ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) { bounds_check_error_loc(loc, index, len(array)); copy(array[index:], array[index+1:]); @@ -400,29 +400,29 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati } -@(builtin) +@builtin clear :: proc{clear_dynamic_array, clear_map}; -@(builtin) +@builtin reserve :: proc{reserve_dynamic_array, reserve_map}; -@(builtin) +@builtin resize :: proc{resize_dynamic_array}; -@(builtin) +@builtin new :: proc{mem.new}; -@(builtin) +@builtin new_clone :: proc{mem.new_clone}; -@(builtin) +@builtin free :: proc{mem.free}; -@(builtin) +@builtin free_all :: proc{mem.free_all}; -@(builtin) +@builtin delete :: proc{ mem.delete_string, mem.delete_cstring, @@ -431,7 +431,7 @@ delete :: proc{ mem.delete_map, }; -@(builtin) +@builtin make :: proc{ mem.make_slice, mem.make_dynamic_array, @@ -443,7 +443,7 @@ make :: proc{ -@(builtin) +@builtin clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) { if m == nil do return; raw_map := (^mem.Raw_Map)(m); @@ -454,19 +454,19 @@ clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) { } } -@(builtin) +@builtin reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) { if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity); } -@(builtin) +@builtin delete_key :: proc(m: ^$T/map[$K]$V, key: K) { if m != nil do __dynamic_map_delete_key(__get_map_header(m), __get_map_key(key)); } -@(builtin) +@builtin append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { if array == nil do return; @@ -485,7 +485,7 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { a.len += arg_len; } } -@(builtin) +@builtin append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) { if array == nil do return; @@ -506,23 +506,23 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) a.len += arg_len; } } -@(builtin) append :: proc{append_elem, append_elems}; +@builtin append :: proc{append_elem, append_elems}; -@(builtin) +@builtin append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) { for arg in args { append(array = array, args = ([]E)(arg), loc = loc); } } -@(builtin) +@builtin clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) { if array != nil do (^mem.Raw_Dynamic_Array)(array).len = 0; } -@(builtin) +@builtin reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool { if array == nil do return false; a := (^mem.Raw_Dynamic_Array)(array); @@ -549,7 +549,7 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal return true; } -@(builtin) +@builtin resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool { if array == nil do return false; a := (^mem.Raw_Dynamic_Array)(array); @@ -582,42 +582,42 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller -@(builtin) +@builtin incl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S { s^ |= {elem}; return s^; } -@(builtin) +@builtin incl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S { for elem in elems do s^ |= {elem}; return s^; } -@(builtin) +@builtin incl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S { s^ |= other; return s^; } -@(builtin) +@builtin excl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S { s^ &~= {elem}; return s^; } -@(builtin) +@builtin excl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S { for elem in elems do s^ &~= {elem}; return s^; } -@(builtin) +@builtin excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S { s^ &~= other; return s^; } -@(builtin) incl :: proc{incl_elem, incl_elems, incl_bit_set}; -@(builtin) excl :: proc{excl_elem, excl_elems, excl_bit_set}; +@builtin incl :: proc{incl_elem, incl_elems, incl_bit_set}; +@builtin excl :: proc{excl_elem, excl_elems, excl_bit_set}; -@(builtin) +@builtin card :: proc(s: $S/bit_set[$E; $U]) -> int { when size_of(S) == 1 { foreign { @(link_name="llvm.ctpop.i8") count_ones :: proc(i: u8) -> u8 --- } @@ -642,7 +642,7 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int { -@(builtin) +@builtin assert :: proc "contextless" (condition: bool, message := "", loc := #caller_location) -> bool { if !condition { p := context.assertion_failure_proc; @@ -654,7 +654,7 @@ assert :: proc "contextless" (condition: bool, message := "", loc := #caller_loc return condition; } -@(builtin) +@builtin panic :: proc "contextless" (message: string, loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { @@ -663,7 +663,7 @@ panic :: proc "contextless" (message: string, loc := #caller_location) -> ! { p("Panic", message, loc); } -@(builtin) +@builtin unimplemented :: proc "contextless" (message := "", loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { @@ -672,7 +672,7 @@ unimplemented :: proc "contextless" (message := "", loc := #caller_location) -> p("not yet implemented", message, loc); } -@(builtin) +@builtin unreachable :: proc "contextless" (message := "", loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 3b184ed12..ca9a77902 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -101,6 +101,7 @@ struct BuildContext { i32 optimization_level; bool show_timings; bool keep_temp_files; + bool ignore_unknown_attributes; bool no_bounds_check; bool no_output_files; bool no_crt; diff --git a/src/checker.cpp b/src/checker.cpp index 94006510a..9cac82911 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2150,7 +2150,9 @@ void check_decl_attributes(CheckerContext *c, Array const &attributes, De } if (!proc(c, elem, name, value, ac)) { - error(elem, "Unknown attribute element name '%.*s'", LIT(name)); + if (!build_context.ignore_unknown_attributes) { + error(elem, "Unknown attribute element name '%.*s'", LIT(name)); + } } } } diff --git a/src/main.cpp b/src/main.cpp index 03368c709..dcea12aa7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -215,6 +215,7 @@ enum BuildFlagKind { BuildFlag_NoCRT, BuildFlag_UseLLD, BuildFlag_Vet, + BuildFlag_IgnoreUnknownAttributes, BuildFlag_COUNT, }; @@ -258,6 +259,7 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None); + add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("-ignore-unknown-attributes"), BuildFlagParam_None); GB_ASSERT(args.count >= 3); Array flag_args = array_slice(args, 3, args.count); @@ -569,6 +571,10 @@ bool parse_build_flags(Array args) { case BuildFlag_Vet: build_context.vet = true; break; + + case BuildFlag_IgnoreUnknownAttributes: + build_context.ignore_unknown_attributes = true; + break; } } diff --git a/src/parser.cpp b/src/parser.cpp index ee67db3be..ab5f1589c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3650,30 +3650,38 @@ Ast *parse_foreign_decl(AstFile *f) { Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, TokenKind close_kind) { Array elems = {}; - Token open = expect_token(f, open_kind); - f->expr_level++; - if (f->curr_token.kind != close_kind) { - elems = array_make(heap_allocator()); - while (f->curr_token.kind != close_kind && - f->curr_token.kind != Token_EOF) { - Ast *elem = nullptr; - elem = parse_ident(f); - if (f->curr_token.kind == Token_Eq) { - Token eq = expect_token(f, Token_Eq); - Ast *value = parse_value(f); - elem = ast_field_value(f, elem, value, eq); - } + Token open = {}; + Token close = {}; - array_add(&elems, elem); + if (f->curr_token.kind == Token_Ident) { + elems = array_make(heap_allocator(), 0, 1); + Ast *elem = parse_ident(f); + array_add(&elems, elem); + } else { + open = expect_token(f, open_kind); + f->expr_level++; + if (f->curr_token.kind != close_kind) { + elems = array_make(heap_allocator()); + while (f->curr_token.kind != close_kind && + f->curr_token.kind != Token_EOF) { + Ast *elem = nullptr; + elem = parse_ident(f); + if (f->curr_token.kind == Token_Eq) { + Token eq = expect_token(f, Token_Eq); + Ast *value = parse_value(f); + elem = ast_field_value(f, elem, value, eq); + } - if (!allow_token(f, Token_Comma)) { - break; + array_add(&elems, elem); + + if (!allow_token(f, Token_Comma)) { + break; + } } } + f->expr_level--; + close = expect_closing(f, close_kind, str_lit("attribute")); } - f->expr_level--; - Token close = expect_closing(f, close_kind, str_lit("attribute")); - Ast *attribute = ast_attribute(f, token, open, close, elems); Ast *decl = parse_stmt(f);