Skip to content

Commit ea61b24

Browse files
author
robertDurst
committed
Allow the calling of methods on attributes
1 parent 4c6f446 commit ea61b24

File tree

16 files changed

+356
-13
lines changed

16 files changed

+356
-13
lines changed

examples/stack.fish

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ Cfn Stack {
6464
if | own...is_empty() == true | {
6565
// do nothing
6666
} else {
67-
// super hacky way of accessing methods on attributes
68-
dec Node temp = new Node { next: void, data: 0 }
69-
temp = own.head
70-
i = temp...data()
67+
i = own.head...data()
7168
}
7269

7370
return i

examples/test.fish

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Cat Foo {
2+
int i
3+
Foo f
4+
}
5+
6+
Cfn Foo {
7+
fun get_i
8+
<- void
9+
-> int
10+
{
11+
return own.i
12+
}
13+
14+
fun bar
15+
<- void
16+
-> int
17+
{
18+
dec int i = 10
19+
i = own.f...get_i()
20+
return i
21+
}
22+
}
23+
24+
start {
25+
dec Foo f = new Foo { i: 1, f: void }
26+
dec Foo b = new Foo { i: 20, f: f }
27+
28+
display_int(b...bar())
29+
display_str("\n")
30+
}

out.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ peek(Stack* own)
7171
}
7272
else
7373
{
74-
Node*temp = construct_Node(NULL,0);
75-
temp = own->head;
76-
i = data(temp);
74+
i = data(own->head);
7775
}
7876

7977
return i;
@@ -143,9 +141,6 @@ main()
143141
print_str("\n");
144142
pop(s);
145143
pop(s);
146-
pop(s);
147-
pop(s);
148-
pop(s);
149144
print_str("Size: ");
150145
print_int(size(s));
151146
print_str("\tTop: ");

src/ast/Ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "Assignment.h"
88
#include "AttributeAccess.h"
9+
#include "AttributeMethodAccess.h"
910
#include "BinaryCompOrArith.h"
1011
#include "BinaryExpression.h"
1112
#include "Block.h"

src/ast/AttributeMethodAccess.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Robert Durst 2019
3+
* Sailfish Programming Language
4+
*/
5+
#pragma once
6+
#include "Ast.h"
7+
#include "AttributeAccess.h"
8+
#include "FunctionCall.h"
9+
#include "Node.h"
10+
#include "Primary.h"
11+
12+
namespace ast
13+
{
14+
class AttributeMethodAccess : public Primary, public Node
15+
{
16+
private:
17+
Identifier* name;
18+
AttributeAccess* attribute;
19+
FunctionCall* func;
20+
Identifier* udt;
21+
22+
public:
23+
// constructor
24+
AttributeMethodAccess(Identifier* n, AttributeAccess* a, FunctionCall* f,
25+
Identifier* u, int lineNum)
26+
: Node(lineNum)
27+
{
28+
name = n;
29+
attribute = a;
30+
func = f;
31+
udt = u;
32+
};
33+
// destructor
34+
~AttributeMethodAccess()
35+
{
36+
delete name;
37+
delete func;
38+
};
39+
// implement Primary
40+
/* virtual */ PrimaryType
41+
getPrimaryType()
42+
{
43+
return Primary::AttributeMethodAccessLiteral;
44+
}
45+
// get method
46+
Identifier*
47+
getName()
48+
{
49+
return name;
50+
}
51+
AttributeAccess*
52+
getAttribute()
53+
{
54+
return attribute;
55+
}
56+
FunctionCall*
57+
getFunctionCall()
58+
{
59+
return func;
60+
}
61+
Identifier*
62+
getUDT()
63+
{
64+
return udt;
65+
}
66+
};
67+
}

src/ast/Primary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Primary
1717
IntegerLiteral,
1818
FloatLiteral,
1919
AttributeAccessLiteral,
20+
AttributeMethodAccessLiteral,
2021
MethodAccessLiteral,
2122
FunctionCallLiteral,
2223
};

src/parser/Parser.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,9 @@ Parser::parseGroupingExpression()
547547

548548
/**
549549
* AttributeAccess := Identifier '.' Identifier
550+
* AttributeMethodAccess := AttributeAccess '...' FunctionCall
550551
*/
551-
ast::AttributeAccess*
552+
ast::Primary*
552553
Parser::parseAttributeAccess(ast::Identifier* udtName)
553554
{
554555
ast::Identifier* name = new ast::Identifier(currentToken->getValue(),
@@ -557,7 +558,57 @@ Parser::parseAttributeAccess(ast::Identifier* udtName)
557558
// consume identifier
558559
getNextUsefulToken();
559560

560-
return new ast::AttributeAccess(name, udtName, currentToken->getLineNum());
561+
ast::AttributeAccess* aa =
562+
new ast::AttributeAccess(name, udtName, currentToken->getLineNum());
563+
564+
// catch the AttributeMethodAccess
565+
if (currentToken->getKind() == Kind::TRIPLE_DOT_TOKEN)
566+
{
567+
// consume '...'
568+
getNextUsefulToken();
569+
570+
return (ast::Primary*)parseAttributeMethodAccess(aa);
571+
}
572+
573+
return (ast::Primary*)aa;
574+
}
575+
576+
/**
577+
* MethodAccess := Identifier '...' Identifier FunctionCall
578+
*/
579+
ast::AttributeMethodAccess*
580+
Parser::parseAttributeMethodAccess(ast::AttributeAccess* aa)
581+
{
582+
ast::Identifier* name = new ast::Identifier(currentToken->getValue(),
583+
currentToken->getLineNum());
584+
585+
// consume identifier
586+
getNextUsefulToken();
587+
588+
// consume '('
589+
getNextUsefulToken();
590+
591+
std::vector<ast::Primary*> idents;
592+
593+
while (currentToken->getKind() != Kind::RPAREN_TOKEN)
594+
{
595+
idents.push_back(parsePrimary());
596+
597+
if (currentToken->isEOF())
598+
{
599+
errorHandler->handle(new Error(currentToken->getLineNum(),
600+
"Missing a right parenthesis."));
601+
}
602+
}
603+
604+
// consume ')'
605+
getNextUsefulToken();
606+
607+
ast::FunctionCall* fc =
608+
new ast::FunctionCall(name, idents, currentToken->getLineNum());
609+
610+
return new ast::AttributeMethodAccess(name, aa, fc, aa->getUDT(),
611+
currentToken->getLineNum());
561612
}
562613

563614
/**

src/parser/Parser.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ class Parser
4949

5050
ast::GroupingExpression* parseGroupingExpression();
5151

52-
ast::AttributeAccess* parseAttributeAccess(ast::Identifier*);
52+
ast::Primary* parseAttributeAccess(ast::Identifier*);
53+
ast::AttributeMethodAccess*
54+
parseAttributeMethodAccess(ast::AttributeAccess*);
5355
ast::MethodAccess* parseMethodAccess(ast::Identifier*);
5456

5557
ast::UnaryExpression* parseUnaryExpression();

src/semantics/TypeChecker.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,84 @@ TypeChecker::getType(ast::Primary* primary)
255255

256256
return truncateType(fullAttributeType);
257257
}
258+
case ast::Primary::AttributeMethodAccessLiteral:
259+
{
260+
ast::AttributeMethodAccess* node =
261+
dynamic_cast<ast::AttributeMethodAccess*>(primary);
262+
263+
// ------- first extract the attribute ------- //
264+
ast::AttributeAccess* subsubnode = node->getAttribute();
265+
266+
std::string attributeName = subsubnode->getAttribute()->getValue();
267+
std::string variableName = subsubnode->getUDT()->getValue();
268+
269+
// hacks: REMOVE ASAP
270+
if (variableName == "own")
271+
{
272+
variableName = curUDT;
273+
}
274+
else
275+
{
276+
// ensure variable exists - double checked so no need for another
277+
// error message
278+
if (!symbolTable->hasVariable(variableName))
279+
{
280+
return "unknown";
281+
}
282+
283+
std::string udtTypeFull = symbolTable->getSymbolType(variableName);
284+
variableName = udtTypeFull.substr(1, udtTypeFull.length());
285+
}
286+
287+
// ensure udt exists - double checked so no need for another
288+
// error message
289+
if (!udtTable->hasUDT(variableName))
290+
{
291+
return "unknown";
292+
}
293+
294+
// ensure attribute exists for udt - double checked so only return error
295+
// once
296+
if (!udtTable->getAttributeSymbolTable(variableName)
297+
->hasVariable(attributeName))
298+
{
299+
return "unknown";
300+
}
301+
302+
// std::string fullAttributeType =
303+
// udtTable->getAttributeSymbolTable(variableName)
304+
// ->getSymbolType(attributeName);
305+
306+
// ------- now extract the method ------- //
307+
std::string methodName = node->getName()->getValue();
308+
std::string variableUDTname = getType(node->getAttribute());
309+
310+
// hacks: REMOVE ASAP
311+
if (variableUDTname == "own")
312+
{
313+
variableUDTname = curUDT;
314+
}
315+
else
316+
{
317+
// ensure variable's udt exists - double checked so no need for
318+
// another error message
319+
if (!udtTable->hasUDT(variableUDTname))
320+
{
321+
return "unknown";
322+
}
323+
}
324+
325+
// ensure metho exists for udt - double checked so no need for another
326+
// error message
327+
if (!udtTable->getMethodSymbolTable(variableUDTname)
328+
->hasVariable(methodName))
329+
{
330+
return "unknown";
331+
}
332+
333+
return truncateType(udtTable->getMethodSymbolTable(variableUDTname)
334+
->getSymbolType(methodName));
335+
}
258336
case ast::Primary::MethodAccessLiteral:
259337
{
260338
ast::MethodAccess* node = dynamic_cast<ast::MethodAccess*>(primary);
@@ -1069,6 +1147,63 @@ TypeChecker::visit(ast::AttributeAccess* node)
10691147
}
10701148
}
10711149

1150+
void
1151+
TypeChecker::visit(ast::AttributeMethodAccess* node)
1152+
{
1153+
visit(node->getAttribute());
1154+
1155+
std::string methodName = node->getName()->getValue();
1156+
std::string variableUDTname = getType(node->getAttribute());
1157+
1158+
std::cout << "HERE: " << variableUDTname << "\n";
1159+
1160+
// hacks: REMOVE ASAP
1161+
if (variableUDTname == "own")
1162+
variableUDTname = curUDT;
1163+
1164+
else
1165+
{
1166+
// ensure variable's udt exists
1167+
if (!udtTable->hasUDT(variableUDTname))
1168+
{
1169+
semanticErrorHandler->handle(new Error(
1170+
node->getUDT()->getLineNum(),
1171+
"Method: " + methodName + " called on nonexistent udt type: " +
1172+
variableUDTname + "."));
1173+
1174+
return;
1175+
}
1176+
}
1177+
1178+
std::string udtType = variableUDTname;
1179+
1180+
// ensure metho exists for udt
1181+
if (!udtTable->getMethodSymbolTable(udtType)->hasVariable(methodName))
1182+
{
1183+
semanticErrorHandler->handle(
1184+
new Error(node->getName()->getLineNum(),
1185+
"Method: " + methodName +
1186+
" does not exist for udt type: " + udtType + "."));
1187+
// abort
1188+
return;
1189+
}
1190+
1191+
// visit function call
1192+
std::string fulltype =
1193+
udtTable->getMethodSymbolTable(udtType)->getSymbolType(methodName);
1194+
1195+
std::vector<std::string> inputs = getFunctionParamTypes(fulltype);
1196+
1197+
// ensure that each of the arguments is supplied and of the proper type
1198+
std::vector<ast::Primary*> args = node->getFunctionCall()->getArguments();
1199+
1200+
compareFunctions(inputs, args, methodName,
1201+
node->getFunctionCall()->getLineNum());
1202+
1203+
for (auto const& arg : args)
1204+
visit(arg);
1205+
}
1206+
10721207
void
10731208
TypeChecker::visit(ast::MethodAccess* node)
10741209
{

src/semantics/TypeChecker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class TypeChecker : public Visitor
9696

9797
// udt attribute and method access
9898
void visit(ast::AttributeAccess*);
99+
void visit(ast::AttributeMethodAccess*);
99100
void visit(ast::MethodAccess*);
100101

101102
// function call

0 commit comments

Comments
 (0)