authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 16:06:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 16:06:17-07:00
loge4b0435946ded78b2d4664bf4cf3cf387fe4a12e
tree2005b5a785eb6c9e3bc3f7810946c6fd0ce5a020
parent580df2f53055a25fcceb2717975270a6523f417e

parseh understands variable declarations

and some initializers such as integers

4 files changed, 144 insertions(+), 6 deletions(-)

doc/langref.md+1-1
...@@ -25,7 +25,7 @@ Import = "import" "String" ";"...@@ -25,7 +25,7 @@ Import = "import" "String" ";"
2525
26RootExportDecl = "export" "Symbol" "String" ";"26RootExportDecl = "export" "Symbol" "String" ";"
2727
28ExternDecl = "extern" FnProto ";"28ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2929
30FnProto = "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)30FnProto = "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)
3131
src/analyze.cpp+4-1
...@@ -90,6 +90,8 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -90,6 +90,8 @@ static AstNode *first_executing_node(AstNode *node) {
90}90}
9191
92ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {92ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
93 // if this assert fails, then parseh generated code that
94 // failed semantic analysis, which isn't supposed to happen
93 assert(!node->owner->c_import_node);95 assert(!node->owner->c_import_node);
9496
95 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,97 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
...@@ -2768,6 +2770,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2768,6 +2770,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2768{2770{
2769 bool is_const = variable_declaration->is_const;2771 bool is_const = variable_declaration->is_const;
2770 bool is_export = (variable_declaration->visib_mod == VisibModExport);2772 bool is_export = (variable_declaration->visib_mod == VisibModExport);
2773 bool is_extern = variable_declaration->is_extern;
27712774
2772 TypeTableEntry *explicit_type = nullptr;2775 TypeTableEntry *explicit_type = nullptr;
2773 if (variable_declaration->type != nullptr) {2776 if (variable_declaration->type != nullptr) {
...@@ -2812,7 +2815,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2812,7 +2815,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2812 buf_sprintf("global variable initializer requires constant expression"));2815 buf_sprintf("global variable initializer requires constant expression"));
2813 }2816 }
2814 }2817 }
2815 } else {2818 } else if (!is_extern) {
2816 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));2819 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
2817 implicit_type = g->builtin_types.entry_invalid;2820 implicit_type = g->builtin_types.entry_invalid;
2818 }2821 }
src/parseh.cpp+131-4
...@@ -97,17 +97,24 @@ static ZigList<AstNode *> *create_empty_directives(Context *c) {...@@ -97,17 +97,24 @@ static ZigList<AstNode *> *create_empty_directives(Context *c) {
97 return allocate<ZigList<AstNode*>>(1);97 return allocate<ZigList<AstNode*>>(1);
98}98}
9999
100static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) {100static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char *var_name,
101 AstNode *type_node, AstNode *init_node)
102{
101 AstNode *node = create_node(c, NodeTypeVariableDeclaration);103 AstNode *node = create_node(c, NodeTypeVariableDeclaration);
102 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);104 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);
103 node->data.variable_declaration.is_const = true;105 node->data.variable_declaration.is_const = is_const;
104 node->data.variable_declaration.visib_mod = c->visib_mod;106 node->data.variable_declaration.visib_mod = c->visib_mod;
105 node->data.variable_declaration.expr = expr_node;107 node->data.variable_declaration.expr = init_node;
106 node->data.variable_declaration.directives = create_empty_directives(c);108 node->data.variable_declaration.directives = create_empty_directives(c);
109 node->data.variable_declaration.type = type_node;
107 normalize_parent_ptrs(node);110 normalize_parent_ptrs(node);
108 return node;111 return node;
109}112}
110113
114static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) {
115 return create_typed_var_decl_node(c, true, var_name, nullptr, expr_node);
116}
117
111static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) {118static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) {
112 assert(child_node);119 assert(child_node);
113 AstNode *node = create_node(c, NodeTypePrefixOpExpr);120 AstNode *node = create_node(c, NodeTypePrefixOpExpr);
...@@ -150,10 +157,24 @@ static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) {...@@ -150,10 +157,24 @@ static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) {
150 AstNode *node = create_node(c, NodeTypeNumberLiteral);157 AstNode *node = create_node(c, NodeTypeNumberLiteral);
151 node->data.number_literal.kind = NumLitUInt;158 node->data.number_literal.kind = NumLitUInt;
152 node->data.number_literal.data.x_uint = x;159 node->data.number_literal.data.x_uint = x;
153
154 return node;160 return node;
155}161}
156162
163static AstNode *create_num_lit_signed(Context *c, int64_t x) {
164 if (x >= 0) {
165 return create_num_lit_unsigned(c, x);
166 }
167 BigNum bn_orig;
168 bignum_init_signed(&bn_orig, x);
169
170 BigNum bn_negated;
171 bignum_negate(&bn_negated, &bn_orig);
172
173 uint64_t uint = bignum_to_twos_complement(&bn_negated);
174 AstNode *num_lit_node = create_num_lit_unsigned(c, uint);
175 return create_prefix_node(c, PrefixOpNegation, num_lit_node);
176}
177
157static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) {178static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) {
158 AstNode *node = create_node(c, NodeTypeArrayType);179 AstNode *node = create_node(c, NodeTypeArrayType);
159 node->data.array_type.size = create_num_lit_unsigned(c, size);180 node->data.array_type.size = create_num_lit_unsigned(c, size);
...@@ -202,6 +223,11 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {...@@ -202,6 +223,11 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
202 return create_prefix_node(c, PrefixOpMaybe, child_node);223 return create_prefix_node(c, PrefixOpMaybe, child_node);
203}224}
204225
226static bool type_is_int(AstNode *type_node) {
227 // TODO recurse through the type table
228 return true;
229}
230
205static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,231static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
206 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)232 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)
207{233{
...@@ -689,6 +715,104 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -689,6 +715,104 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
689 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));715 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
690}716}
691717
718static void visit_var_decl(Context *c, const VarDecl *var_decl) {
719 Buf *name = buf_create_from_str(decl_name(var_decl));
720
721 switch (var_decl->getTLSKind()) {
722 case VarDecl::TLS_None:
723 break;
724 case VarDecl::TLS_Static:
725 emit_warning(c, var_decl, "ignoring variable '%s' - static thread local storage\n", buf_ptr(name));
726 return;
727 case VarDecl::TLS_Dynamic:
728 emit_warning(c, var_decl, "ignoring variable '%s' - dynamic thread local storage\n", buf_ptr(name));
729 return;
730 }
731
732 QualType qt = var_decl->getType();
733 AstNode *type_node = make_qual_type_node(c, qt, var_decl);
734 if (!type_node) {
735 emit_warning(c, var_decl, "ignoring variable '%s' - unresolved type\n", buf_ptr(name));
736 return;
737 }
738
739 bool is_extern = var_decl->hasExternalStorage();
740 bool is_static = var_decl->isFileVarDecl();
741 bool is_const = qt.isConstQualified();
742
743 if (is_static && !is_extern) {
744 if (!var_decl->hasInit()) {
745 emit_warning(c, var_decl, "ignoring variable '%s' - no initializer\n", buf_ptr(name));
746 return;
747 }
748 APValue *ap_value = var_decl->evaluateValue();
749 if (!ap_value) {
750 emit_warning(c, var_decl, "ignoring variable '%s' - unable to evaluate initializer\n", buf_ptr(name));
751 return;
752 }
753 AstNode *init_node;
754 switch (ap_value->getKind()) {
755 case APValue::Int:
756 {
757 if (!type_is_int(type_node)) {
758 emit_warning(c, var_decl,
759 "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));
760 return;
761 }
762 llvm::APSInt aps_int = ap_value->getInt();
763 if (aps_int.isSigned()) {
764 if (aps_int > INT64_MAX || aps_int < INT64_MIN) {
765 emit_warning(c, var_decl,
766 "ignoring variable '%s' - initializer overflow\n", buf_ptr(name));
767 return;
768 } else {
769 init_node = create_num_lit_signed(c, aps_int.getExtValue());
770 }
771 } else {
772 if (aps_int > UINT64_MAX) {
773 emit_warning(c, var_decl,
774 "ignoring variable '%s' - initializer overflow\n", buf_ptr(name));
775 return;
776 } else {
777 init_node = create_num_lit_unsigned(c, aps_int.getExtValue());
778 }
779 }
780 break;
781 }
782 case APValue::Uninitialized:
783 case APValue::Float:
784 case APValue::ComplexInt:
785 case APValue::ComplexFloat:
786 case APValue::LValue:
787 case APValue::Vector:
788 case APValue::Array:
789 case APValue::Struct:
790 case APValue::Union:
791 case APValue::MemberPointer:
792 case APValue::AddrLabelDiff:
793 emit_warning(c, var_decl,
794 "ignoring variable '%s' - unrecognized initializer value kind\n", buf_ptr(name));
795 return;
796 }
797
798 AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node);
799 c->root->data.root.top_level_decls.append(var_node);
800 c->root_name_table.put(name, true);
801 return;
802 }
803
804 if (is_extern) {
805 AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr);
806 var_node->data.variable_declaration.is_extern = true;
807 c->root->data.root.top_level_decls.append(var_node);
808 c->root_name_table.put(name, true);
809 return;
810 }
811
812 emit_warning(c, var_decl, "ignoring variable '%s' - non-extern, non-static variable\n", buf_ptr(name));
813 return;
814}
815
692static bool decl_visitor(void *context, const Decl *decl) {816static bool decl_visitor(void *context, const Decl *decl) {
693 Context *c = (Context*)context;817 Context *c = (Context*)context;
694818
...@@ -705,6 +829,9 @@ static bool decl_visitor(void *context, const Decl *decl) {...@@ -705,6 +829,9 @@ static bool decl_visitor(void *context, const Decl *decl) {
705 case Decl::Record:829 case Decl::Record:
706 visit_record_decl(c, static_cast<const RecordDecl *>(decl));830 visit_record_decl(c, static_cast<const RecordDecl *>(decl));
707 break;831 break;
832 case Decl::Var:
833 visit_var_decl(c, static_cast<const VarDecl *>(decl));
834 break;
708 default:835 default:
709 emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());836 emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());
710 }837 }
test/run_tests.cpp+8
...@@ -2011,6 +2011,14 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",...@@ -2011,6 +2011,14 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
2011 )SOURCE", 2,2011 )SOURCE", 2,
2012 "pub const THING1 = 1234;",2012 "pub const THING1 = 1234;",
2013 "pub const THING2 = THING1;");2013 "pub const THING2 = THING1;");
2014
2015
2016 add_parseh_case("variables", R"SOURCE(
2017extern int extern_var;
2018static const int int_var = 13;
2019 )SOURCE", 2,
2020 "pub extern var extern_var: c_int;",
2021 "pub const int_var: c_int = 13;");
2014}2022}
20152023
2016static void print_compiler_invocation(TestCase *test_case) {2024static void print_compiler_invocation(TestCase *test_case) {