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_PUB 0x8U
|
||||||
#define FE_NODE_COMPTIME 0x10U
|
#define FE_NODE_COMPTIME 0x10U
|
||||||
#define FE_NODE_EXTERN 0x20U
|
#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 {
|
typedef struct FeAst {
|
||||||
FeArena arena;
|
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,
|
static void store_into(Lower *L, FeIrPlace dst, Slot value, FeNode *n,
|
||||||
unsigned long size);
|
unsigned long size);
|
||||||
static void lower_for(Lower *L, FeNode *n);
|
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 void lower_match(Lower *L, FeNode *n);
|
||||||
static int enum_has_payload(const FeType *t);
|
static int enum_has_payload(const FeType *t);
|
||||||
static void lower_global(Lower *L, FeNode *n);
|
static void lower_global(Lower *L, FeNode *n);
|
||||||
@@ -673,7 +675,7 @@ static Slot lower_expr_core(Lower *L, FeNode *n)
|
|||||||
unsigned scale;
|
unsigned scale;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
unsigned addr;
|
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);
|
base = lower_expr(L, n->a);
|
||||||
indexable_parts(L, base, bt, &data, &length, n);
|
indexable_parts(L, base, bt, &data, &length, n);
|
||||||
index = as_value(L, lower_expr(L, n->b), n->b);
|
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;
|
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.
|
/* Three shapes share the keyword.
|
||||||
|
|
||||||
for i in a..b { } counts
|
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; }
|
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)) {
|
else if(eat(p,FE_TOK_LBRACKET)) {
|
||||||
m=toknode(p,FE_N_INDEX,t);m->a=n;
|
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(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)) { if(!is(p,FE_TOK_RBRACKET)) m->c=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;
|
want(p,FE_TOK_RBRACKET,"expected ']' after index");n=m;
|
||||||
}
|
}
|
||||||
else if(eat(p,FE_TOK_DOT)) {
|
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