Skip to content

Commit e98054d

Browse files
authored
Allow returning composite literal addr from funcs
1 parent 4ebaa8a commit e98054d

File tree

5 files changed

+58
-48
lines changed

5 files changed

+58
-48
lines changed

examples/lisp/ev.um

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import "../../import/std.um"
22

33

44
type Expr* = struct {
5-
atom: str
6-
val: int
7-
car, cdr: ^Expr
5+
atom: str
6+
val: int
7+
car, cdr: ^Expr
88
}
99

1010

@@ -44,17 +44,12 @@ fn (e: ^Expr) toBool*(): bool {
4444

4545

4646
fn strExpr*(s: str): ^Expr {
47-
e := new(Expr)
48-
e.atom = s
49-
return e
47+
return &Expr{s, 0, null, null}
5048
}
5149

5250

5351
fn intExpr*(i: int): ^Expr {
54-
e := new(Expr)
55-
e.atom = "<number>"
56-
e.val = i
57-
return e
52+
return &Expr{"<number>", i, null, null}
5853
}
5954

6055

@@ -86,10 +81,8 @@ fn cdr*(x: ^Expr): ^Expr {
8681
}
8782

8883

89-
fn cons*(x, y: ^Expr): ^Expr {
90-
z := new(Expr)
91-
z^ = Expr{"", 0, x, y}
92-
return z
84+
fn cons*(x, y: ^Expr): ^Expr {
85+
return &Expr{"", 0, x, y}
9386
}
9487

9588

examples/lisp/parse.um

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ fn (p: ^Parser) parse(): ^ev.Expr {
3333

3434
// Parse atom
3535
p.lexer.check(lex.tokAtom)
36-
res := new(ev.Expr)
37-
res.atom = p.lexer.tok.name
38-
res.val = p.lexer.tok.val
36+
res := &ev.Expr{p.lexer.tok.name, p.lexer.tok.val, null, null}
3937
p.lexer.next()
4038
return res
4139

src/umka_expr.c

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@ static void doCopyResultToTempVar(Compiler *comp, Type *type)
3939
}
4040

4141

42+
static void doEscapeToHeap(Compiler *comp, Type *ptrType)
43+
{
44+
// Allocate heap
45+
genPushIntConst(&comp->gen, typeSize(&comp->types, ptrType->base));
46+
genCallBuiltin(&comp->gen, TYPE_PTR, BUILTIN_NEW);
47+
doCopyResultToTempVar(comp, ptrType);
48+
49+
// Save heap pointer
50+
genDup(&comp->gen);
51+
genPopReg(&comp->gen, VM_REG_COMMON_0);
52+
53+
// Copy to heap and use heap pointer
54+
genSwapAssign(&comp->gen, ptrType->base->kind, typeSize(&comp->types, ptrType->base));
55+
genPushReg(&comp->gen, VM_REG_COMMON_0);
56+
}
57+
58+
4259
static void doIntToRealConv(Compiler *comp, Type *dest, Type **src, Const *constant, bool lhs)
4360
{
4461
BuiltinFunc builtin = lhs ? BUILTIN_REAL_LHS : BUILTIN_REAL;
@@ -214,22 +231,8 @@ static void doValueToInterfaceConv(Compiler *comp, Type *dest, Type **src, Const
214231
if (constant)
215232
comp->error.handler(comp->error.context, "Conversion to interface is not allowed in constant expressions");
216233

217-
Type *srcPtrType = typeAddPtrTo(&comp->types, &comp->blocks, *src);
218-
219-
// Allocate heap
220-
genPushIntConst(&comp->gen, typeSize(&comp->types, *src));
221-
genCallBuiltin(&comp->gen, TYPE_PTR, BUILTIN_NEW);
222-
doCopyResultToTempVar(comp, srcPtrType);
223-
224-
// Save heap pointer
225-
genDup(&comp->gen);
226-
genPopReg(&comp->gen, VM_REG_COMMON_0);
227-
228-
// Copy to heap and use heap pointer (interfaces accept only pointers as their dynamic types)
229-
genSwapAssign(&comp->gen, (*src)->kind, typeSize(&comp->types, *src));
230-
genPushReg(&comp->gen, VM_REG_COMMON_0);
231-
232-
*src = srcPtrType;
234+
*src = typeAddPtrTo(&comp->types, &comp->blocks, *src);
235+
doEscapeToHeap(comp, *src);
233236
doPtrToInterfaceConv(comp, dest, src, constant);
234237
}
235238

@@ -1121,14 +1124,20 @@ static void parseCompositeLiteral(Compiler *comp, Type **type, Const *constant)
11211124
}
11221125

11231126

1124-
static void parseTypeCastOrCompositeLiteral(Compiler *comp, Ident *ident, Type **type, Const *constant, bool *isVar, bool *isCall)
1127+
static void parseTypeCastOrCompositeLiteral(Compiler *comp, Ident *ident, Type **type, Const *constant, bool *isVar, bool *isCall, bool *isCompLit)
11251128
{
11261129
*type = parseType(comp, ident);
11271130

11281131
if (comp->lex.tok.kind == TOK_LPAR)
1132+
{
11291133
parseTypeCast(comp, type, constant);
1134+
*isCompLit = false;
1135+
}
11301136
else if (comp->lex.tok.kind == TOK_LBRACE)
1137+
{
11311138
parseCompositeLiteral(comp, type, constant);
1139+
*isCompLit = true;
1140+
}
11321141
else
11331142
comp->error.handler(comp->error.context, "Type cast or composite literal expected");
11341143

@@ -1317,7 +1326,7 @@ static void parseCallSelector(Compiler *comp, Type **type, Const *constant, bool
13171326

13181327

13191328
// selectors = {derefSelector | indexSelector | fieldSelector | callSelector}.
1320-
static void parseSelectors(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall)
1329+
static void parseSelectors(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall, bool *isCompLit)
13211330
{
13221331
while (comp->lex.tok.kind == TOK_CARET || comp->lex.tok.kind == TOK_LBRACKET ||
13231332
comp->lex.tok.kind == TOK_PERIOD || comp->lex.tok.kind == TOK_LPAR)
@@ -1333,27 +1342,32 @@ static void parseSelectors(Compiler *comp, Type **type, Const *constant, bool *i
13331342
case TOK_LPAR: parseCallSelector (comp, type, constant, isVar, isCall); break;
13341343
default: break;
13351344
} // switch
1345+
1346+
*isCompLit = false;
13361347
} // while
13371348
}
13381349

13391350

13401351
// designator = (primary | typeCast | compositeLiteral) selectors.
1341-
void parseDesignator(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall)
1352+
void parseDesignator(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall, bool *isCompLit)
13421353
{
1354+
*isCompLit = false;
1355+
13431356
Ident *ident = NULL;
13441357
if (comp->lex.tok.kind == TOK_IDENT && (ident = parseQualIdent(comp)) && ident->kind != IDENT_TYPE)
13451358
parsePrimary(comp, ident, type, constant, isVar, isCall);
13461359
else
1347-
parseTypeCastOrCompositeLiteral(comp, ident, type, constant, isVar, isCall);
1360+
parseTypeCastOrCompositeLiteral(comp, ident, type, constant, isVar, isCall, isCompLit);
13481361

1349-
parseSelectors(comp, type, constant, isVar, isCall);
1362+
parseSelectors(comp, type, constant, isVar, isCall, isCompLit);
13501363
}
13511364

13521365

13531366
// designatorList = designator {"," designator}.
13541367
void parseDesignatorList(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall)
13551368
{
1356-
parseDesignator(comp, type, constant, isVar, isCall);
1369+
bool isCompLit;
1370+
parseDesignator(comp, type, constant, isVar, isCall, &isCompLit);
13571371

13581372
if (comp->lex.tok.kind == TOK_COMMA)
13591373
{
@@ -1374,8 +1388,8 @@ void parseDesignatorList(Compiler *comp, Type **type, Const *constant, bool *isV
13741388

13751389
lexNext(&comp->lex);
13761390

1377-
bool fieldIsVar, fieldIsCall;
1378-
parseDesignator(comp, &fieldType, NULL, &fieldIsVar, &fieldIsCall);
1391+
bool fieldIsVar, fieldIsCall, fieldIsCompLit;
1392+
parseDesignator(comp, &fieldType, NULL, &fieldIsVar, &fieldIsCall, &fieldIsCompLit);
13791393

13801394
if (fieldIsVar != *isVar || fieldIsCall != *isCall)
13811395
comp->error.handler(comp->error.context, "Inconsistent designator list");
@@ -1400,8 +1414,8 @@ static void parseFactor(Compiler *comp, Type **type, Const *constant)
14001414
case TOK_FN:
14011415
{
14021416
// A designator that isVar is always an addressable quantity (a structured type or a pointer to a value type)
1403-
bool isVar, isCall;
1404-
parseDesignator(comp, type, constant, &isVar, &isCall);
1417+
bool isVar, isCall, isCompLit;
1418+
parseDesignator(comp, type, constant, &isVar, &isCall, &isCompLit);
14051419
if (isVar)
14061420
{
14071421
if (!typeStructured(*type))
@@ -1498,14 +1512,19 @@ static void parseFactor(Compiler *comp, Type **type, Const *constant)
14981512

14991513
lexNext(&comp->lex);
15001514

1501-
bool isVar, isCall;
1502-
parseDesignator(comp, type, constant, &isVar, &isCall);
1515+
bool isVar, isCall, isCompLit;
1516+
parseDesignator(comp, type, constant, &isVar, &isCall, &isCompLit);
1517+
15031518
if (!isVar)
15041519
comp->error.handler(comp->error.context, "Unable to take address");
15051520

15061521
// A value type is already a pointer, a structured type needs to have it added
15071522
if (typeStructured(*type))
15081523
*type = typeAddPtrTo(&comp->types, &comp->blocks, *type);
1524+
1525+
// Allow returning addresses of composite literals from functions
1526+
if (isCompLit)
1527+
doEscapeToHeap(comp, *type);
15091528
break;
15101529
}
15111530

src/umka_expr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void doImplicitTypeConv (Compiler *comp, Type *dest, Type **src, Const *constant
1010
void doApplyOperator (Compiler *comp, Type **type, Type **rightType, Const *constant, Const *rightConstant, TokenKind op, bool apply, bool convertLhs);
1111

1212
Ident *parseQualIdent (Compiler *comp);
13-
void parseDesignator (Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall);
13+
void parseDesignator (Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall, bool *isCompLit);
1414
void parseDesignatorList(Compiler *comp, Type **type, Const *constant, bool *isVar, bool *isCall);
1515
void parseExpr (Compiler *comp, Type **type, Const *constant);
1616
void parseExprList (Compiler *comp, Type **type, Type *destType, Const *constant);

tests/gc.um

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ fn f2() {
2929

3030
fn g2(): ^int {a := new(int); return a}
3131

32-
fn h2(): st {
32+
fn h2(): ^st {
3333
d := new(int)
34-
return st{x: 7, p: d, y: 5, q: d}
34+
return &st{x: 7, p: d, y: 5, q: d}
3535
}
3636

3737
fn test*() {

0 commit comments

Comments
 (0)