aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2015-12-08 15:31:43 -0700
committerAndrew Kelley <superjoe30@gmail.com>2015-12-08 15:31:43 -0700
commite8550814c5e4387e8b758736a1254a5c3b32674e (patch)
treee1f669d947987121be234fdd6bb7ccc55e4d7b2f /src/analyze.cpp
parent6e0c3dc173507b92fc04515659454044f918efbb (diff)
downloadzig-e8550814c5e4387e8b758736a1254a5c3b32674e.tar.gz
zig-e8550814c5e4387e8b758736a1254a5c3b32674e.zip
support assigning to arrays
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp62
1 files changed, 40 insertions, 22 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index c6f50ff5d3..4436457b01 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -10,6 +10,9 @@
#include "zig_llvm.hpp"
#include "os.hpp"
+static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+ TypeTableEntry *expected_type, AstNode *node);
+
static AstNode *first_executing_node(AstNode *node) {
switch (node->type) {
case NodeTypeFnCallExpr:
@@ -476,6 +479,35 @@ LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {
}
}
+static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+ AstNode *node)
+{
+ TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
+ node->data.array_access_expr.array_ref_expr);
+
+ TypeTableEntry *return_type;
+
+ if (array_type->id == TypeTableEntryIdArray) {
+ return_type = array_type->data.array.child_type;
+ } else {
+ if (array_type->id != TypeTableEntryIdInvalid) {
+ add_node_error(g, node, buf_sprintf("array access of non-array"));
+ }
+ return_type = g->builtin_types.entry_invalid;
+ }
+
+ TypeTableEntry *subscript_type = analyze_expression(g, import, context, nullptr,
+ node->data.array_access_expr.subscript);
+ if (subscript_type->id != TypeTableEntryIdInt &&
+ subscript_type->id != TypeTableEntryIdInvalid)
+ {
+ add_node_error(g, node,
+ buf_sprintf("array subscripts must be integers"));
+ }
+
+ return return_type;
+}
+
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
@@ -593,6 +625,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
case BinOpTypeAssign:
{
AstNode *lhs_node = node->data.bin_op_expr.op1;
+ TypeTableEntry *expected_rhs_type = nullptr;
if (lhs_node->type == NodeTypeSymbol) {
Buf *name = &lhs_node->data.symbol;
LocalVariableTableEntry *var = find_local_variable(context, name);
@@ -601,18 +634,19 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
add_node_error(g, lhs_node,
buf_sprintf("cannot assign to constant variable"));
} else {
- analyze_expression(g, import, context, var->type,
- node->data.bin_op_expr.op2);
+ expected_rhs_type = var->type;
}
} else {
add_node_error(g, lhs_node,
buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name)));
}
-
+ } else if (lhs_node->type == NodeTypeArrayAccessExpr) {
+ expected_rhs_type = analyze_array_access_expr(g, import, context, lhs_node);
} else {
add_node_error(g, lhs_node,
buf_sprintf("expected a bare identifier"));
}
+ analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);
return_type = g->builtin_types.entry_void;
break;
}
@@ -736,25 +770,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
}
case NodeTypeArrayAccessExpr:
- {
- // here we are always reading the array
- TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
- node->data.array_access_expr.array_ref_expr);
- if (array_type->id == TypeTableEntryIdArray) {
- TypeTableEntry *subscript_type = analyze_expression(g, import, context,
- nullptr, node->data.array_access_expr.subscript);
- if (subscript_type->id != TypeTableEntryIdInt) {
- add_node_error(g, node,
- buf_sprintf("array subscripts must be integers"));
- }
- return_type = array_type->data.array.child_type;
- } else {
- add_node_error(g, node, buf_sprintf("array access of non-array"));
- return_type = g->builtin_types.entry_invalid;
- }
-
- break;
- }
+ // for reading array access; assignment handled elsewhere
+ return_type = analyze_array_access_expr(g, import, context, node);
+ break;
case NodeTypeNumberLiteral:
// TODO: generic literal int type
return_type = g->builtin_types.entry_i32;