lower: 슬라이싱
x[a..b] 는 인덱스가 아니라 포인터와 길이를 만든다. 양쪽 끝을 -- 서로에 대해, 그리고 있는 것에 대해 -- 검사한 뒤에 포인터를 만든다. 유효한 범위의 빈 슬라이스는 괜찮고 끝보다 늦게 시작하는 것은 아니다. 파서가 x[a] 와 x[a..] 를 구분하지 못했다. 둘 다 b 만 있고 c 가 없어서 모양이 같았다. '..' 가 있었으면 노드에 표시한다. 정수 출력이 된다: fizz 12345 -678
This commit is contained in:
@@ -44,6 +44,9 @@ struct FeNode {
|
||||
#define FE_NODE_PUB 0x8U
|
||||
#define FE_NODE_COMPTIME 0x10U
|
||||
#define FE_NODE_EXTERN 0x20U
|
||||
/* An index expression that had `..` in it, so it makes a slice rather than
|
||||
reaching an element. `x[a]` and `x[a..]` are otherwise the same shape. */
|
||||
#define FE_NODE_SLICE 0x40U
|
||||
|
||||
typedef struct FeAst {
|
||||
FeArena arena;
|
||||
|
||||
+46
-1
@@ -62,6 +62,8 @@ static void lower_stmt(Lower *L, FeNode *n);
|
||||
static void store_into(Lower *L, FeIrPlace dst, Slot value, FeNode *n,
|
||||
unsigned long size);
|
||||
static void lower_for(Lower *L, FeNode *n);
|
||||
static Slot lower_slice(Lower *L, FeNode *n);
|
||||
static void guard(Lower *L, unsigned ok, FeIrTrap reason, unsigned long line);
|
||||
static void lower_match(Lower *L, FeNode *n);
|
||||
static int enum_has_payload(const FeType *t);
|
||||
static void lower_global(Lower *L, FeNode *n);
|
||||
@@ -673,7 +675,7 @@ static Slot lower_expr_core(Lower *L, FeNode *n)
|
||||
unsigned scale;
|
||||
unsigned offset;
|
||||
unsigned addr;
|
||||
if (n->c || !n->b) { fail(L, "a slice expression", n); return slot_void(); }
|
||||
if (n->flags & FE_NODE_SLICE) return lower_slice(L, n);
|
||||
base = lower_expr(L, n->a);
|
||||
indexable_parts(L, base, bt, &data, &length, n);
|
||||
index = as_value(L, lower_expr(L, n->b), n->b);
|
||||
@@ -973,6 +975,49 @@ static void lower_while(Lower *L, FeNode *n)
|
||||
L->b = done;
|
||||
}
|
||||
|
||||
/* `x[a..b]` makes a pointer and a length out of part of something indexable.
|
||||
Both ends are checked -- against each other and against what is there --
|
||||
before the pointer is formed. An empty slice of a valid range is fine; one
|
||||
that starts past its end is not. */
|
||||
static Slot lower_slice(Lower *L, FeNode *n)
|
||||
{
|
||||
FeType *bt = n->a ? n->a->sem_type : 0;
|
||||
FeType *elem = bt ? bt->elem : 0;
|
||||
FeType *t = n->sem_type;
|
||||
Slot base = lower_expr(L, n->a);
|
||||
unsigned data;
|
||||
unsigned length;
|
||||
unsigned from;
|
||||
unsigned to;
|
||||
unsigned local;
|
||||
unsigned scale;
|
||||
unsigned off;
|
||||
unsigned at;
|
||||
unsigned count;
|
||||
indexable_parts(L, base, bt, &data, &length, n);
|
||||
from = n->b ? as_value(L, lower_expr(L, n->b), n->b)
|
||||
: fe_ir_const(L->m, L->b, FE_IR_I32, 0);
|
||||
to = n->c ? as_value(L, lower_expr(L, n->c), n->c) : length;
|
||||
if (!L->c->no_checks) {
|
||||
unsigned ordered = fe_ir_binary(L->m, L->b, FE_IR_LE, FE_IR_I32,
|
||||
from, to, 1);
|
||||
unsigned within;
|
||||
guard(L, ordered, FE_TRAP_BOUNDS, n->loc.line);
|
||||
within = fe_ir_binary(L->m, L->b, FE_IR_LE, FE_IR_I32, to, length, 1);
|
||||
guard(L, within, FE_TRAP_BOUNDS, n->loc.line);
|
||||
}
|
||||
scale = fe_ir_const(L->m, L->b, FE_IR_I32, (long)ir_size(elem));
|
||||
off = fe_ir_binary(L->m, L->b, FE_IR_MUL, FE_IR_I32, from, scale, 1);
|
||||
at = fe_ir_binary(L->m, L->b, FE_IR_ADD, FE_IR_PTR, data, off, 1);
|
||||
count = fe_ir_binary(L->m, L->b, FE_IR_SUB, FE_IR_I32, to, from, 1);
|
||||
local = scratch(L, t, "slice");
|
||||
fe_ir_store(L->m, L->b, fe_ir_at_local(local, SLICE_PTR_OFFSET), at,
|
||||
FE_IR_PTR);
|
||||
fe_ir_store(L->m, L->b, fe_ir_at_local(local, SLICE_LEN_OFFSET), count,
|
||||
FE_IR_I32);
|
||||
return slot_place(fe_ir_at_local(local, 0), FE_IR_MEM, ir_size(t));
|
||||
}
|
||||
|
||||
/* Three shapes share the keyword.
|
||||
|
||||
for i in a..b { } counts
|
||||
|
||||
+2
-2
@@ -124,8 +124,8 @@ static FeNode *postfix(FeParser *p)
|
||||
if(eat(p,FE_TOK_LPAREN)) { m=toknode(p,FE_N_CALL,t); m->a=n; while(!is(p,FE_TOK_RPAREN)&&!is(p,FE_TOK_EOF)){fe_node_add(m,delimited_expr(p));if(!eat(p,FE_TOK_COMMA))break;} want(p,FE_TOK_RPAREN,"expected ')' after call"); n=m; }
|
||||
else if(eat(p,FE_TOK_LBRACKET)) {
|
||||
m=toknode(p,FE_N_INDEX,t);m->a=n;
|
||||
if(is(p,FE_TOK_DOTDOT)) m->b=0; else m->b=delimited_expr(p);
|
||||
if(eat(p,FE_TOK_DOTDOT)) { if(!is(p,FE_TOK_RBRACKET)) m->c=delimited_expr(p); }
|
||||
if(is(p,FE_TOK_DOTDOT)) { m->b=0; m->flags|=FE_NODE_SLICE; } else m->b=delimited_expr(p);
|
||||
if(eat(p,FE_TOK_DOTDOT)) { m->flags|=FE_NODE_SLICE; if(!is(p,FE_TOK_RBRACKET)) m->c=delimited_expr(p); }
|
||||
want(p,FE_TOK_RBRACKET,"expected ']' after index");n=m;
|
||||
}
|
||||
else if(eat(p,FE_TOK_DOT)) {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// EXIT:0
|
||||
// OUTPUT:fizz 12345 -678
|
||||
unit printnum;
|
||||
import std.io;
|
||||
import std.fmt;
|
||||
|
||||
fn show(v: i32) -> void {
|
||||
var buf: [16]u8 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
||||
let n: usize = fmt.fmt_i32(buf[..], v);
|
||||
io.print(" ");
|
||||
io.print(buf[0..n]);
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
io.print("fizz");
|
||||
show(12345);
|
||||
show(0 - 678);
|
||||
io.print("\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user