Skip to content

Commit 79c7992

Browse files
committed
Mostly work on the bootstrap compiler.
Andrew did a lot of work on the bootstrap compiler, and a few tests were added and bugs fixed in order to aid Andrew.
1 parent 9d6357b commit 79c7992

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+3895
-217
lines changed

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ clean:
143143
for file in tests/*.rn crypto_class/*.rn errortests/*.rn; do exeFile=$$(echo "$$file" | sed 's/.rn$$//'); rm -f "$$exeFile"; done
144144
cd runtime ; make clean
145145
cd bootstrap/database ; make clean
146+
cd bootstrap/cbackend ; make clean
147+
146148

147149
obj: include/dedatabase.h llvm/lldatabase.h
148150
mkdir -p obj/database obj/llvm obj/parse obj/runtime obj/src obj/util obj/rpc obj/bind obj/transformer

TODO

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Add LLVM compiler hints and optmizations as described at
4040
Support named parameters, like Python.
4141

4242
## Medium Term
43+
Support negative indicies, like Python, in slices to indicate size relative to length of the array.
4344
Write tests to verify that constant time processing of secrets is achieved. E.g. if (issecret(foo)...
4445
Add support for fixed-sized arrays for improved speed.
4546
Make modular inverse constant time.

bind/bind.c

+14-1
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,17 @@ void deQueueSignature(deSignature signature) {
550550
}
551551
}
552552

553+
// Some variables are never bound, and have no datatype. Delete them.
554+
static void removeUnusedVariables(deClass theClass) {
555+
deVariable var;
556+
deBlock block = deClassGetSubBlock(theClass);
557+
deSafeForeachBlockVariable(block, var) {
558+
if (deVariableGetDatatype(var) == deDatatypeNull) {
559+
deVariableDestroy(var);
560+
}
561+
} deEndSafeBlockVariable;
562+
}
563+
553564
// Bind signatures until done. This can be called multiple times, to bind new
554565
// statements and functions.
555566
void deBindAllSignatures(void) {
@@ -567,7 +578,9 @@ void deBindAllSignatures(void) {
567578
updateSignature(signature);
568579
checkSignatureReturnType(signature);
569580
if (deBlockIsConstructor(deSignatureGetBlock(signature))) {
570-
deGenerateDefaultMethods(deDatatypeGetClass(deSignatureGetReturnType(signature)));
581+
deClass theClass = deDatatypeGetClass(deSignatureGetReturnType(signature));
582+
removeUnusedVariables(theClass);
583+
deGenerateDefaultMethods(theClass);
571584
}
572585
}
573586
}

bind/bindexpr.c

+23-4
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,13 @@ static deVariable findNamedParam(deBlock block, deExpression param) {
10671067
return var;
10681068
}
10691069

1070+
// Check that the expression's datatype is not none.
1071+
static void checkNotNone(deExpression expr) {
1072+
if (deExpressionGetDatatype(expr) == deNoneDatatypeCreate()) {
1073+
deExprError(expr, "Expression has none type.");
1074+
}
1075+
}
1076+
10701077
// Find call datatypes. For default parameters with default values that are
10711078
// not specified by the caller, use deNullDatatype, as this will be bound when
10721079
// expression the function.
@@ -1097,7 +1104,9 @@ static deDatatypeArray findCallDatatypes(deBlock scopeBlock,
10971104
var = deVariableGetNextBlockVariable(var);
10981105
} else if (isMethodCall(access)) {
10991106
// Add the type of the object on the left of the dot expression as self parameter.
1100-
deDatatype selfType = deExpressionGetDatatype(deExpressionGetFirstExpression(access));
1107+
deExpression selfExpr = deExpressionGetFirstExpression(access);
1108+
checkNotNone(selfExpr);
1109+
deDatatype selfType = deExpressionGetDatatype(selfExpr);
11011110
if (deDatatypeArrayGetUsedDatatype(paramTypes) == 0) {
11021111
deExprError(access, "Function %s lacks a self parameter, but is called as a method",
11031112
deFunctionGetName(function));
@@ -1109,6 +1118,7 @@ static deDatatypeArray findCallDatatypes(deBlock scopeBlock,
11091118
deExpression param = deExpressionGetFirstExpression(params);
11101119
bool foundNamedParam = false;
11111120
while (param != deExpressionNull) {
1121+
checkNotNone(param);
11121122
foundNamedParam |= deExpressionGetType(param) == DE_EXPR_NAMEDPARAM;
11131123
if (!foundNamedParam) {
11141124
if (var == deVariableNull || deVariableGetType(var) != DE_VAR_PARAMETER) {
@@ -1222,6 +1232,7 @@ static void markConstructorClassBound(deSignature signature) {
12221232
deSignatureSetBound(signature, true);
12231233
deQueueEventBlockedBindings(deSignatureGetReturnEvent(signature));
12241234
deClassSetBound(theClass, true);
1235+
deCreateBlockVariables(deClassGetSubBlock(theClass), deFunctionGetSubBlock(function));
12251236
}
12261237

12271238
// Bind a call expression.
@@ -1859,6 +1870,10 @@ static deBindRes bindExpression(deBlock scopeBlock, deExpression expression, boo
18591870
deExpressionSetIsType(expression, true);
18601871
deExpressionSetDatatype(expression, deBoolDatatypeCreate());
18611872
break;
1873+
case DE_EXPR_NONETYPE:
1874+
deExpressionSetIsType(expression, true);
1875+
deExpressionSetDatatype(expression, deNoneDatatypeCreate());
1876+
break;
18621877
case DE_EXPR_AS:
18631878
utExit("Unexpected expression type");
18641879
break;
@@ -1942,9 +1957,11 @@ static void postProcessBoundStatement(deBlock scopeBlock, deBinding binding) {
19421957
deStatementSetInstantiated(statement, deBindingInstantiated(binding));
19431958
deStatementType type = deStatementGetType(statement);
19441959
if (type == DE_STATEMENT_RETURN || type == DE_STATEMENT_YIELD) {
1960+
deExpression expr = deStatementGetExpression(statement);
19451961
deDatatype datatype = deNoneDatatypeCreate();
19461962
if (deStatementGetExpression(statement) != deExpressionNull) {
1947-
datatype = deExpressionGetDatatype(deStatementGetExpression(statement));
1963+
checkNotNone(expr);
1964+
datatype = deExpressionGetDatatype(expr);
19481965
}
19491966
updateSignatureReturnType(deBindingGetSignature(binding), datatype);
19501967
} else if (type == DE_STATEMENT_TYPESWITCH) {
@@ -2023,8 +2040,10 @@ void deBindStatement(deBinding binding) {
20232040
if (datatype != deDatatypeNull &&
20242041
!deDatatypeMatchesTypeExpression(scopeBlock, datatype, typeExpr)) {
20252042
deCurrentSignature = deBindingGetSignature(binding);
2026-
deError(deExpressionGetLine(typeExpr), "Failed type constraint: %s",
2027-
deDatatypeGetTypeString(datatype));
2043+
deSigError(deCurrentSignature, "Failed type constraint: variable %s expected type %s, got: %s",
2044+
deVariableGetName(variable),
2045+
deEscapeString(deExpressionToString(typeExpr)),
2046+
deDatatypeGetTypeString(datatype));
20282047
}
20292048
break;
20302049
}

bind/create_vars.c

+34-11
Original file line numberDiff line numberDiff line change
@@ -29,39 +29,62 @@ static void createVariableIfMissing(deBlock scopeBlock, deExpression expr) {
2929
}
3030
}
3131

32+
// Determine if this is a member access in a constructor.
33+
static bool isMemberAccessInConstructor(deBlock scopeBlock, deExpression expr) {
34+
deClass theClass = deBlockGetOwningClass(scopeBlock);
35+
if (theClass == deClassNull || deExpressionGetType(expr) != DE_EXPR_DOT) {
36+
return false;
37+
}
38+
deExpression leftExpr = deExpressionGetFirstExpression(expr);
39+
if (deExpressionGetType(leftExpr) != DE_EXPR_IDENT) {
40+
return false;
41+
}
42+
deFunction constructor = deTemplateGetFunction(deClassGetTemplate(theClass));
43+
deVariable selfVar = deBlockGetFirstVariable(deFunctionGetSubBlock(constructor));
44+
return deVariableGetSym(selfVar) == deExpressionGetName(leftExpr);
45+
}
46+
3247
// Create variables when we find assignment expressions that assign to an identifier.
3348
static void createExpressionVariables(deBlock scopeBlock, deExpression expr) {
3449
if (deExpressionGetType(expr) == DE_EXPR_EQUALS) {
3550
deExpression target = deExpressionGetFirstExpression(expr);
3651
if (deExpressionGetType(target) == DE_EXPR_IDENT) {
3752
createVariableIfMissing(scopeBlock, target);
3853
}
54+
if (isMemberAccessInConstructor(scopeBlock, target)) {
55+
createVariableIfMissing(scopeBlock, deExpressionGetLastExpression(target));
56+
}
3957
}
4058
deExpression child;
4159
deForeachExpressionExpression(expr, child) {
4260
createExpressionVariables(scopeBlock, child);
4361
} deEndExpressionExpression;
4462
}
4563

64+
// Create any variables declared by the statement.
65+
void deCreateStatementVariables(deBlock scopeBlock, deStatement statement) {
66+
deExpression expr = deStatementGetExpression(statement);
67+
if (expr != deExpressionNull) {
68+
createExpressionVariables(scopeBlock, expr);
69+
}
70+
deBlock subBlock = deStatementGetSubBlock(statement);
71+
if (subBlock != deBlockNull) {
72+
deCreateBlockVariables(scopeBlock, subBlock);
73+
}
74+
}
75+
4676
// Create variables in the block from assignment expressions of the form:
4777
// IDENT = expression
4878
// Then, recurse into child functions.
49-
static void createBlockVariables(deBlock scopeBlock, deBlock block) {
79+
void deCreateBlockVariables(deBlock scopeBlock, deBlock block) {
5080
deStatement statement;
5181
deForeachBlockStatement(block, statement) {
52-
deExpression expr = deStatementGetExpression(statement);
53-
if (expr != deExpressionNull) {
54-
createExpressionVariables(scopeBlock, expr);
55-
}
56-
deBlock subBlock = deStatementGetSubBlock(statement);
57-
if (subBlock != deBlockNull) {
58-
createBlockVariables(scopeBlock, subBlock);
59-
}
82+
deCreateStatementVariables(scopeBlock, statement);
6083
} deEndBlockStatement;
6184
deFunction func;
6285
deForeachBlockFunction(block, func) {
6386
deBlock subBlock = deFunctionGetSubBlock(func);
64-
createBlockVariables(subBlock, subBlock);
87+
deCreateBlockVariables(subBlock, subBlock);
6588
} deEndBlockFunction;
6689
}
6790

@@ -70,5 +93,5 @@ static void createBlockVariables(deBlock scopeBlock, deBlock block) {
7093
// assignment expression that could create a local variable otherwise.
7194
void deCreateLocalAndGlobalVariables(void) {
7295
deBlock scopeBlock = deRootGetBlock(deTheRoot);
73-
createBlockVariables(scopeBlock, scopeBlock);
96+
deCreateBlockVariables(scopeBlock, scopeBlock);
7497
}

bootstrap/Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ parse/package.rn\
4343
parse/pegparser.rn\
4444
parse/rule.rn\
4545
parse/token.rn\
46+
cbackend/cbuilder.rn\
47+
cbackend/cemitter.rn\
48+
cbackend/clanguageclasses.rn\
49+
cbackend/cruntime.rn\
50+
cbackend/escapestring.rn\
51+
cbackend/float2string.rn\
52+
cbackend/int2cstring.rn\
53+
cbackend/package.rn\
54+
cbackend/stringstream.rn\
55+
cbackend/stringwriter.rn\
4656
rune.rn
4757

4858
rune: $(SRC)

bootstrap/cbackend/cbuilder.rn

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Copyright 2024 Google LLC.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import database as db
16+
17+
use clanguageclasses
18+
use escapestring
19+
20+
relation DoublyLinked CBuilder CBlock cascade
21+
22+
class CBuilder(self) {
23+
self.currentParamList = null(CParamList)
24+
self.currentExprList = null(CExprList)
25+
self.program = CProgram()
26+
self.currentBlock = null(CBlock)
27+
28+
func build(self, module: db.Function) -> CProgram {
29+
module.genC(self)
30+
return self.program
31+
}
32+
33+
func addDeclaration(self, dec: CDeclaration) {
34+
self.program.insertCDeclaration(dec)
35+
}
36+
37+
func openScope(self) {
38+
}
39+
40+
func closeScope(self) {
41+
}
42+
43+
func openBlock(self, location: db.Location?) {
44+
self.currentBlock = CBlock(location)
45+
//self.cblocks().appendCBlock(block)
46+
//self.appendCBlock(block)
47+
self.appendCBlock(CBlock(location))
48+
}
49+
50+
func closeBlock(self) -> CBlock {
51+
//block = self.currentCBlock
52+
block = self.lastCBlock!
53+
//self.currentCBlock = block.prevCBlockCBuilder
54+
//self.cblocks().removeCBlock(block)
55+
self.removeCBlock(block)
56+
return block
57+
}
58+
59+
func addStatement(self, statement: CStatement) {
60+
if isnull(self.currentBlock) {
61+
self.program.addStatementToMain(statement)
62+
} else {
63+
self.currentBlock.appendCStatement(statement)
64+
}
65+
}
66+
67+
func openParamList(self) {
68+
assert isnull(self.currentParamList)
69+
self.currentParamList = CParamList()
70+
}
71+
72+
func closeParamList(self) -> CParamList {
73+
assert !isnull(self.currentParamList)
74+
params = self.currentParamList!
75+
self.currentParamList = null(CParamList)
76+
return params
77+
}
78+
79+
func addParam(self, param: CParameter) {
80+
assert !isnull(self.currentParamList)
81+
self.currentParamList.appendCParameter(param)
82+
}
83+
84+
func cParameter(self, location: db.Location, name: string, type: CTypeExpr) -> CParameter {
85+
return CParameter(location, name, type)
86+
}
87+
88+
func cType(self, type: CType) -> CTypeExpr {
89+
return CTypeExpr(type)
90+
}
91+
92+
/* Rune expressions *********************************************************************/
93+
94+
func openExprList(self) {
95+
assert isnull(self.currentExprList)
96+
self.currentExprList = CExprList()
97+
}
98+
99+
func closeExprList(self) -> CExpr {
100+
assert !isnull(self.currentExprList)
101+
list = self.currentExprList!
102+
self.currentExprList = null(CExprList)
103+
return CExpr(list)
104+
}
105+
106+
func addExpr(self, expr: CExpr) {
107+
assert !isnull(self.currentExprList)
108+
self.currentExprList.appendCExpr(expr)
109+
}
110+
111+
func cStringLiteral(self, value: string) -> CExpr {
112+
return CExpr(CLiteral(escapeString(value)))
113+
}
114+
115+
func cBoolLiteral(self, value: bool) -> CExpr {
116+
return CExpr(CLiteral(value))
117+
}
118+
119+
func cIntLiteral(self, value: db.Bigint) -> CExpr {
120+
return CExpr(CLiteral(value))
121+
}
122+
123+
func cUintLiteral(self, value: Uint) -> CExpr {
124+
return CExpr(CLiteral(value))
125+
}
126+
127+
func cFloatLiteral(self, value: Float) -> CExpr {
128+
return CExpr(CLiteral(value))
129+
}
130+
131+
func cUnaryMinus(self, location: db.Location, arg: CExpr) -> CExpr {
132+
return CExpr(CPrefixOperator(location, CPrefixOperator.Type.UnaryMinus, arg))
133+
}
134+
135+
func cBinaryOperator(self, location: db.Location, op: CBinaryOperator.Type,
136+
left: CExpr, right: CExpr) -> CExpr {
137+
return CExpr(CBinaryOperator(location, op, left, right))
138+
}
139+
140+
func cCall(self, location: db.Location, name: string | CRuntimeFunction, args: CExpr) -> CExpr {
141+
return CExpr(CCall(location, name, args))
142+
}
143+
144+
145+
146+
/* Rune statements *******************************************************************/
147+
148+
func cPrintlnStatement(self, location: db.Location, args: CExpr) -> CStatement {
149+
return CStatement(self.cCall(location, CRuntimeFunction.Printf, args))
150+
}
151+
152+
func cFunDef(self, location: db.Location, name: string, returnType: CTypeExpr,
153+
params: CParamList, body: CBlock) -> CDeclaration {
154+
return CDeclaration(CFunctionDeclaration(
155+
location, name, returnType, params, body))
156+
}
157+
158+
}
159+

0 commit comments

Comments
 (0)