Skip to content

Commit a65582a

Browse files
committed
Merged upstream changes.
This set of changes add the initial files for the bootstrap parser generator, which are in an intermediate dev state. Catch/throw semi-broken support was also added. Stack unwinding is not done, so memory leaks occur on throw.
1 parent e2a3f44 commit a65582a

Some content is hidden

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

49 files changed

+963
-269
lines changed

bind/bind.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,8 @@ static void reportEvent(deEvent event) {
598598
}
599599
deIdent undefinedIdent = deEventGetUndefinedIdent(event);
600600
utAssert(undefinedIdent != deIdentNull);
601-
deReportError(deExpressionGetLine(deIdentGetFirstExpression(undefinedIdent)),
602-
"Undefined identifier %s", deIdentGetName(undefinedIdent));
601+
deExpression expression = deBindingGetFirstExpression(binding);
602+
deExprError(expression, "Undefined identifier %s", deIdentGetName(undefinedIdent));
603603
}
604604

605605
// Report errors for any undefined or unbound identifiers that remain, and

bind/bindexpr.c

+6
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,12 @@ static void postProcessBoundStatement(deBlock scopeBlock, deBinding binding) {
19521952
selectMatchingCase(scopeBlock, binding);
19531953
} else if (type == DE_STATEMENT_PRINT || type == DE_STATEMENT_THROW) {
19541954
dePostProcessPrintStatement(statement);
1955+
} else if (type == DE_STATEMENT_IF) {
1956+
deExpression expression = deStatementGetExpression(statement);
1957+
deDatatype datatype = deExpressionGetDatatype(expression);
1958+
if (datatype == deDatatypeNull || deDatatypeGetType(datatype) != DE_TYPE_BOOL) {
1959+
deExprError(expression, "If statement requires a boolean condition");
1960+
}
19551961
}
19561962
}
19571963

bootstrap/Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
RUNE=../rune
1516
SRC=\
1617
rune.rn \
1718
database/expr.rn \
@@ -21,7 +22,10 @@ database/line.stdout \
2122
database/root.rn
2223

2324
rune: $(SRC)
24-
rune -g rune.rn
25+
$(RUNE) -g rune.rn
26+
27+
test: $(SRCS)
28+
$(RUNE) -g -t rune.rn
2529

2630
clean:
2731
rm -f rune rune.ll rune.log

bootstrap/database/Makefile

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
RUNE=../../rune
1616

17-
RUNE_TESTS=bigint block expr function statement value
17+
RUNE_TESTS=bigint block expr function statement value filepath location
1818

1919
runtests: $(RUNE_TESTS)
2020
for test in $(RUNE_TESTS); do "./$$test"; done
@@ -37,5 +37,11 @@ block: block.rn
3737
function: function.rn
3838
$(RUNE) -g function.rn
3939

40+
filepath: filepath.rn
41+
$(RUNE) -g filepath.rn
42+
43+
location: location.rn
44+
$(RUNE) -g location.rn
45+
4046
clean:
4147
rm -f $(RUNE_TESTS) *.ll

bootstrap/database/filepath.rn

+18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use root
2222
class Filepath(self, path: string, parent: Filepath?, isPackage: bool) {
2323
self.sym = Sym.new(path)
2424
self.isPackage = isPackage
25+
self.text = "" // Call the readFile() method to initialize this.
2526
getRoot().insertFilepath(self)
2627
if !isnull(parent) {
2728
parent!.appendChildFilepath(self)
@@ -53,7 +54,24 @@ class Filepath(self, path: string, parent: Filepath?, isPackage: bool) {
5354
}
5455
return path[pos:path.length()]
5556
}
57+
58+
// Read the text of the filepath into self.text.
59+
// Throws an error if there are any problems.
60+
func readFile(self) {
61+
file = io.open(self.sym.name, "r")
62+
if isnull(file) {
63+
throw "Unable to read file ", self.sym.name
64+
}
65+
self.text = file!.read()
66+
}
5667
}
5768

5869
relation Hashed Root Filepath cascade ("sym")
5970
relation DoublyLinked Filepath:"Parent" Filepath:"Child" cascade
71+
72+
unittest constructorTest {
73+
rootFilepath = Filepath("rootdir", null(Filepath), false)
74+
childFilepath = Filepath("test", rootFilepath, true)
75+
rootFilepath.destroy()
76+
println "passed"
77+
}

bootstrap/database/location.rn

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2023 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+
// This should replace the Line class in the database. For now, it is local to
16+
// the parser generator.
17+
18+
use filepath
19+
20+
class Location(self, filepath: Filepath, pos:u32, len: u32, line: u32) {
21+
self.pos = pos
22+
self.len = len
23+
self.line = line
24+
filepath.appendLocation(self)
25+
26+
// Write the line to stdout, with a filename and line number prefix.
27+
func dump(self) {
28+
filepath = self.filepath
29+
assert !isnull(filepath)
30+
path = filepath!.getRelativePath()
31+
if path.length() > 0 {
32+
println "File %s, line %u:" % (path, self.line)
33+
}
34+
if filepath!.text.length() > 0 {
35+
self.printLineAndCarots()
36+
}
37+
}
38+
39+
// Like dump(), but prints msg.
40+
func error(self, msg) {
41+
filepath = self.filepath
42+
assert !isnull(filepath)
43+
path = filepath!.getRelativePath()
44+
if path.length() > 0 {
45+
println "File %s, line %u: %s" % (path, self.line, msg)
46+
}
47+
if filepath!.text.length() > 0 {
48+
self.printLineAndCarots()
49+
}
50+
}
51+
52+
func printLineAndCarots(self) {
53+
start = self.findLineStart()
54+
end = self.findLineEnd()
55+
println self.filepath!.text[start:end]
56+
for i in range(self.pos - start) {
57+
print " "
58+
}
59+
for i in range(self.len) {
60+
print "^"
61+
}
62+
println
63+
}
64+
65+
func findLineStart(self) -> u32 {
66+
pos = self.pos
67+
while pos != 0 {
68+
pos -= 1
69+
c = self.filepath!.text[pos]
70+
if c == '\n' {
71+
return pos + 1
72+
}
73+
}
74+
return 0u32
75+
}
76+
77+
func findLineEnd(self) -> u32 {
78+
pos = self.pos
79+
while pos < <pos>self.filepath!.text.length() {
80+
if self.filepath!.text[pos] == '\n' {
81+
return pos
82+
}
83+
pos += 1
84+
}
85+
return <pos>self.filepath!.text.length()
86+
}
87+
}
88+
89+
relation DoublyLinked Filepath Location
90+
91+
unittest {
92+
rootFilepath = Filepath.new("testdata", null(Filepath), false)
93+
filepath = Filepath.new("testdata/hello", rootFilepath, false)
94+
location1 = Location(filepath, 0u32, 5u32, 1u32)
95+
location2 = Location(filepath, 7u32, 6u32, 1u32)
96+
filepath.readFile()
97+
location1.dump()
98+
location2.dump()
99+
}

bootstrap/database/location.stdout

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
File testdata/hello, line 1:
2+
Hello, World!
3+
^^^^^
4+
File testdata/hello, line 1:
5+
Hello, World!
6+
^^^^^^

bootstrap/database/package.rn

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use root
16-
use line
17-
use filepath
1815
use bigint
1916
use datatype
20-
use value
2117
use expr
18+
use filepath
19+
use line
20+
use location
21+
use root
22+
use value

bootstrap/database/testdata/hello

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello, World!

bootstrap/database/value.rn

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Value(self: Value, value: string | bool | Int | Uint | Bigint | Float | Sy
4444
self.intVal = null(Bigint)
4545
self.floatVal = 0.0f64
4646
self.symVal = null(Sym)
47+
// We need a tagged union here, but for now we'll just bloat this class.
4748
typeswitch value {
4849
string => self.stringVal = value
4950
bool => self.boolVal = value

bootstrap/parsegen/Makefile

+12-6
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,32 @@
1313
# limitations under the License.
1414

1515
RUNE=../../rune
16+
RNFLAGS=-g -r ..
1617

17-
RUNE_TESTS=parser char lexer
18+
RUNE_TESTS=char lexer parser token keytab
1819

1920
all: runtests parsergen
2021

2122
runtests: $(RUNE_TESTS)
2223
for test in $(RUNE_TESTS); do "./$$test"; done
2324

2425
parsergen: parsergen.rn
25-
$(RUNE) -g parsergen.rn
26+
$(RUNE) $(RNFLAGS) parsergen.rn
2627

2728
parser: parser.rn lexer.rn char.rn
28-
$(RUNE) -g parser.rn
29+
$(RUNE) $(RNFLAGS) parser.rn
2930

3031
char: char.rn
31-
$(RUNE) -g char.rn
32+
$(RUNE) $(RNFLAGS) char.rn
3233

3334
lexer: lexer.rn char.rn
34-
$(RUNE) -g lexer.rn
35+
$(RUNE) $(RNFLAGS) lexer.rn
36+
37+
token: token.rn
38+
$(RUNE) $(RNFLAGS) token.rn
39+
40+
keytab: keytab.rn
41+
$(RUNE) -g keytab.rn
3542

36-
clean:
3743
clean:
3844
rm -f $(RUNE_TESTS) *.ll parsergen

0 commit comments

Comments
 (0)