grading pass (though may be still buggy)

This commit is contained in:
ridethepig 2023-03-27 12:54:18 +08:00
parent c5bbdde30b
commit 67cdb55125
6 changed files with 244 additions and 84 deletions

View File

@ -1,15 +1,31 @@
class Ok1{};
class Ok2_1 inherits Ok1 {};
class Ok2_2 inherits Ok1 {};
class ErrTest {
errCase(): Bool {
{
case (new NOEXIST) of
x1: Bool => true;
x2: Int => x2 <- 10;
x3: NOEXIST => x3 + 10;
x3: NOEXIST => new Object;
x4: Int => x4 + true;
x4: Object => 111;
x5: SELF_TYPE => self;
x5: SELF_TYPE => self;
x1:
Bool => true;
x2:
Int => x2 <- 10;
x3:
NOEXIST => x3 + 10;
x3:
NOEXIST => new Object;
x4:
Int => x4 + true;
x4:
Object => 111;
x5:
SELF_TYPE => self;
x5:
SELF_TYPE => self;
esac;
1 + case (new Ok2_2) of
x1 : Ok2_1 => new Ok2_1;
x2 : Ok2_2 => new Ok2_2;
esac;
}
};
@ -28,6 +44,7 @@ class ErrTest {
errLet(): Object {
let x1:NOEXIST, x2:Int<-10, x3:NOEXIST <- x1, x4:Bool <- 10 in {
x1 <- attr1 + x1;
10 + (self <- 10 + false);
}
};
attr1: NOEXIST;
@ -46,12 +63,17 @@ class Main {
attr1: Bool <- (new Err5).hello();
attr2: Int <- (new Err5).bye();
self(): SELF_TYPE { new SELF_TYPE };
attr3: NOEXIST <- 10;
main(): Object {
{
let x:Int in {
attr3.hello(1 + false) + 10;
let x:Int, y:NOEXIST in {
x1 <- x + 1;
x <- false;
x <- x1;
attr3 * 10;
y * 10;
if (y) then y else attr3 fi;
};
while (1 + 1) loop
x1 <- true
@ -60,7 +82,8 @@ class Main {
(new ErrMethods).errMethod(true + false);
(new ErrMethods).errMethod2(false, false);
(new ErrMethods).errMethod2(true + false);
attr2@Main.hello();
attr2@SELF_TYPE.hello();
self@Main.self();
}
};
};

View File

@ -88,6 +88,10 @@ class Main inherits DummyMain {
main: Bool <- true + false;
};
class SELF_TYPE {
};
class Err5 {
ala: Bool <- 20;
-- hello() : Object {{ala <- ala + 1;}};

View File

@ -0,0 +1,3 @@
#!/bin/bash
set -ex
./lexer $* | ./parser $* > debug_input.in

View File

@ -1,7 +1,7 @@
class C {
a : Int;
b : Bool;
init(x : Int, y : Bool) : C {
init(x : Int, y : Bool) : SELF_TYPE {
{
a <- x;
b <- y;
@ -11,7 +11,15 @@ class C {
};
Class Main {
good() : Bool { true };
self_method() : SELF_TYPE { self };
main():C {
(new C).init(1,true)
{
new SELF_TYPE.good();
(new C).init(1,true);
isvoid true;
isvoid false;
isvoid x;
}
};
};

View File

@ -100,7 +100,10 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
/* first scan: de-duplicate class definitions*/
for (auto i = classes->first(); classes->more(i); i = classes->next(i)) {
auto class_i = static_cast<class__class*>(classes->nth(i));
if (name_to_node.find(class_i->get_name()) != name_to_node.end()) {
if (class_i->get_name() == SELF_TYPE) {
semant_error(class_i) << "Redefinition of basic class SELF_TYPE.\n";
}
else if (name_to_node.find(class_i->get_name()) != name_to_node.end()) {
semant_error(class_i) << "Class " << class_i->get_name() << " was previously defined.\n";
}
else {
@ -161,12 +164,16 @@ void ClassTable::symtab_dump(Symbol class_name) {
std::cerr << "--------\n\n";
}
Symbol ClassTable::symtab_object_lookup_parent(Symbol class_name, Symbol object_name) {
Symbol ClassTable::symtab_object_lookup_parent(Class_ class_i, Symbol object_name) const {
return symtab_object_lookup_parent(class_to_name(class_i), object_name);
}
Symbol ClassTable::symtab_object_lookup_parent(Symbol class_name, Symbol object_name) const {
assert(name_to_node.find(class_name) != name_to_node.end());
auto class_node = name_to_node[class_name];
auto parent_node= class_node->parent;
auto class_node = name_to_node.find(class_name)->second;
auto parent_node= class_node;
while (parent_node) {
auto result = _symtab_obj[parent_node->get_class()->get_name()]->probe(object_name);
auto result = _symtab_obj.find(parent_node->get_class()->get_name())->second->lookup(object_name);
// only need to lookup in the top scope, because attributes all reside in top scope
if (result) return result;
parent_node = parent_node->parent;
@ -174,12 +181,16 @@ Symbol ClassTable::symtab_object_lookup_parent(Symbol class_name, Symbol object_
return nullptr;
}
method_class* ClassTable::symtab_method_lookup_parent(Symbol class_name, Symbol method_name) {
method_class* ClassTable::symtab_method_lookup_parent(Class_ class_i, Symbol method_name) const {
return symtab_method_lookup_parent(class_to_name(class_i), method_name);
}
method_class* ClassTable::symtab_method_lookup_parent(Symbol class_name, Symbol method_name) const {
assert(name_to_node.find(class_name) != name_to_node.end());
auto class_node = name_to_node[class_name];
auto parent_node= class_node->parent;
auto class_node = name_to_node.find(class_name)->second;
auto parent_node= class_node;
while (parent_node) {
auto result = _symtab_met[parent_node->get_class()->get_name()]->probe(method_name);
auto result = _symtab_met.find(parent_node->get_class()->get_name())->second->lookup(method_name);
// only need to lookup in the top scope, because attributes all reside in top scope
if (result) return result;
parent_node = parent_node->parent;
@ -256,7 +267,7 @@ void ClassTable::install_all_features() {
<< "In redefined method " << cur_method->get_name()
<< ", return type " << cur_method->get_return_type()
<< " is different from original return type" << overridden_method->get_return_type()
<< "\n";
<< ".\n";
_error_flag = true;
}
else if (cur_method->get_formals()->len() != overridden_method->get_formals()->len()) {
@ -281,7 +292,7 @@ void ClassTable::install_all_features() {
<< "In redefined method " << cur_method->get_name()
<< ", parameter type " << cur_formal->get_type_decl()
<< " is different from original type" << overridden_formal->get_type_decl()
<< "\n";
<< ".\n";
_error_flag = true;
break;
}
@ -473,12 +484,21 @@ ostream& ClassTable::semant_error()
/*
* Query the Inheritance Graph if T1 <= T0
*
* Note: if T1 inherits from(or is) T0, then T1 <= T0
*
* Warning: if the type doesn't exist, by default return `TRUE` to stop
* error cascading
*/
bool ClassTable::conform(Symbol T1, Symbol T0) const {
if (T1 == T0) return true;
if (!class_exist(T0) || !class_exist(T1))
return true;
auto cur_node_itr = name_to_node.find(T1);
if (cur_node_itr == name_to_node.end()){
std::cerr << "Comform: Escaping type T1 = " << T1 << "\n";
assert(cur_node_itr != name_to_node.end());
}
auto cur_node = cur_node_itr->second;
while (cur_node) {
if (cur_node->get_class()->get_name() == T0) {
@ -489,17 +509,52 @@ bool ClassTable::conform(Symbol T1, Symbol T0) const {
return false;
}
bool ClassTable::conform_self(Symbol T1, Symbol T0, Symbol env_class) const {
if (T1 == T0) return true;
/*
* Add a special rule for SELF_TYPE: SELF_TYPE_c <= T0 if C <= T0
*/
if (T1 == SELF_TYPE) {
return conform(env_class, T0);
}
if (T0 == SELF_TYPE) {
return false;
}
else {
return conform(T1, T0);
}
}
bool ClassTable::conform_self(Symbol T1, Symbol T0, Class_ env_class) const {
return conform_self(T1, T0, class_to_name(env_class));
}
bool ClassTable::class_exist(Symbol class_id) const {
if (class_id == SELF_TYPE) return true;
return name_to_node.find(class_id) != name_to_node.end();
}
/*
* Check Class existence allowing `SELF_TYPE` to be a valid type name
* `SELF_TYPE` may be used in the following places: No other uses are permitted.
* - new SELF TYPE
* - return type of a method,
* - declared type of a let variable
* - declared type of an attribute
*/
bool ClassTable::class_exist_self(Symbol class_id) const {
if (class_id == SELF_TYPE) return true;
else return class_exist(class_id);
}
Symbol ClassTable::lub(Symbol T1, Symbol T2) const {
if (T1 == T2) return T1;
auto node1_iter = name_to_node.find(T1);
auto node2_iter = name_to_node.find(T2);
assert(node1_iter != name_to_node.end());
assert(node2_iter != name_to_node.end());
// assert(node1_iter != name_to_node.end());
// assert(node2_iter != name_to_node.end());
if (node1_iter == name_to_node.end() || node2_iter == name_to_node.end()) {
return Object;
}
auto node1 = node1_iter->second;
auto node2 = node2_iter->second;
ClassGraphNode* node_lower = nullptr;
@ -530,6 +585,11 @@ Symbol ClassTable::lub(Symbol T1, Symbol T2) const {
return node_lower->get_class()->get_name();
}
Symbol ClassTable::lub(Symbol T1, Symbol T2, Symbol env_class) const {
if (T1 == SELF_TYPE) T1 = env_class;
if (T2 == SELF_TYPE) T2 = env_class;
return lub(T1, T2);
}
/* This is the entry point to the semantic checker.
Your checker should do the following two things:
@ -589,12 +649,11 @@ void attr_class::semant(Class_ cur_class, ClassTable * classtable)
* Check if Declared Type is defined, if so, do nothing because already
* in AST; else, error report and set its type to Object
*/
if (!classtable->class_exist(type_decl)) {
if (!classtable->class_exist_self(type_decl)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Class " << type_decl
<< " of attribute " << name
<< " is undefined.\n";
this->type_decl = Object;
}
/*
* Attr-Init:
@ -603,13 +662,13 @@ void attr_class::semant(Class_ cur_class, ClassTable * classtable)
*/
if (typeid(*init) != typeid(no_expr_class)) {
auto rhs_type = init->semant(cur_class, classtable);
std::cerr << "attr init rhs type=" << rhs_type << "\n";
if (!classtable->conform(rhs_type, type_decl)) {
// std::cerr << "attr init rhs type=" << rhs_type << "\n";
if (!classtable->conform_self(rhs_type, type_decl, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Inferred type " << rhs_type
<< " of initialization of attribute " << name
<< " does not conform to declared type " << type_decl
<< " .\n";
<< ".\n";
this->type_decl = Object;
}
}
@ -623,7 +682,11 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
auto formal_i = static_cast<formal_class*>(formals->nth(i));
auto formal_i_name = formal_i->get_name();
auto formal_i_type = formal_i->get_type_decl();
if (symtab_obj->probe(formal_i_name) == nullptr) {
if (formal_i_name == self) {
classtable->semant_error(cur_class->get_filename(), formal_i)
<< "\'self\' cannot be the name of a formal parameter.\n";
}
else if (symtab_obj->probe(formal_i_name) == nullptr) {
symtab_obj->addid(formal_i_name, formal_i_type);
}
else {
@ -639,8 +702,14 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
}
}
auto expr_type = this->expr->semant(cur_class, classtable);
if (!classtable->class_exist_self(this->return_type)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Undefined return type " << this->return_type
<< " in method " << this->name
<< ".\n";
}
symtab_obj->exitscope();
if (!classtable->conform(expr_type, this->return_type)) {
if (!classtable->conform_self(expr_type, this->return_type, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Inferred return type " << expr_type
<< " of method " << this->name
@ -656,24 +725,26 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
*/
Symbol assign_class::semant(Class_ cur_class, ClassTable* classtable)
{
auto lhs_type = classtable->symtab_obj(cur_class)->lookup(name);
// auto lhs_type = classtable->symtab_obj(cur_class)->lookup(name);
if (this->name == self) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Cannot assign to 'self'.\n";
}
auto lhs_type = classtable->symtab_object_lookup_parent(cur_class, name);
if (lhs_type == nullptr) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Assignment to undeclared variable " << name << "\n";
<< "Assignment to undeclared variable " << name << ".\n";
lhs_type = Object;
}
auto rhs_type = this->expr->semant(cur_class, classtable);
if (!classtable->conform(rhs_type, lhs_type)) {
if (!classtable->conform_self(rhs_type, lhs_type, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Type " << rhs_type
<< " of assigned expression does not conform to declared type " << lhs_type
<< " of identifier " << name
<< " .\n";
this->type = Object;
<< ".\n";
}
else {
this->type = rhs_type;
}
return this->type;
}
@ -687,13 +758,19 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
_param_type.push_back(param_i_type);
}
if (!classtable->class_exist(this->type_name)) {
if (this->type_name == SELF_TYPE){
classtable->semant_error(cur_class->get_filename(), this)
<< "Static dispatch to undefined class " << this->type_name
<< "Static dispatch to SELF_TYPE.\n";
}
else {
classtable->semant_error(cur_class->get_filename(), this)
<< "Static dispatch on undefined class " << this->type_name
<< ".\n";
}
this->type = Object;
return this->type;
}
if (!classtable->conform(expr_type, this->type_name)) {
if (!classtable->conform_self(expr_type, this->type_name, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Expression type " << expr_type
<< " does not conform to declared static dispatch type " << this->type_name
@ -701,18 +778,19 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
this->type = Object;
return this->type;
}
auto symtab_method = classtable->symtab_met(this->type_name);
auto cur_method = symtab_method->lookup(name);
// auto symtab_method = classtable->symtab_met(this->type_name);
// auto cur_method = symtab_method->lookup(name);
auto cur_method = classtable->symtab_method_lookup_parent(this->type_name, this->name);
if (cur_method == nullptr) {
classtable->semant_error(cur_class->get_filename(), this)
<< " Dispatch to undefined method " << name
<< "Static dispatch to undefined method " << name
<< ".\n";
this->type = Object;
return Object;
}
if (actual->len() != cur_method->get_formals()->len()) {
classtable->semant_error(cur_class->get_filename(), this)
<< " Method " << name
<< "Method " << name
<< " called with wrong number of arguments.\n";
this->type = Object;
return Object;
@ -721,7 +799,7 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
auto _param_type_iter = _param_type.begin();
for (auto i = formals->first(); formals->more(i); i = formals->next(i)) {
auto formal_i = static_cast<formal_class*>(formals->nth(i));
if (!classtable->conform(*_param_type_iter, formal_i->get_type_decl())) {
if (!classtable->conform_self(*_param_type_iter, formal_i->get_type_decl(), cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "In call of method " << cur_method->get_name()
<< ", type " << *_param_type_iter
@ -734,6 +812,7 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
auto return_type = cur_method->get_return_type();
if (return_type == SELF_TYPE) {
return_type = expr_type;
// if expr_type (T_0) is SELF_TYPE, then dispath type just keep it
}
this->type = return_type;
return this->type;
@ -747,35 +826,53 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
*/
Symbol dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
{
auto expr_type = expr->semant(cur_class, classtable);
std::vector<Symbol> _param_type;
auto expr_type = expr->semant(cur_class, classtable); // T_0
std::vector<Symbol> _param_type; // T_i
for (auto i = actual->first(); actual->more(i); i = actual->next(i)) {
auto param_i = actual->nth(i);
auto param_i_type = param_i->semant(cur_class, classtable);
_param_type.push_back(param_i_type);
}
auto symtab_method = classtable->symtab_met(expr_type);
assert(symtab_method);
auto cur_method = symtab_method->lookup(name);
if (cur_method == nullptr) {
Symbol method_env_class = expr_type; // T_0'
if (expr_type == SELF_TYPE) {
method_env_class = classtable->class_to_name(cur_class);
}
if (!classtable->class_exist(method_env_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< " Dispatch to undefined method " << name
<< "Dispatch on undefined class " << method_env_class
<< ".\n";
this->type = Object;
return this->type;
}
// auto symtab_method = classtable->symtab_met(method_env_class);
// auto cur_method = symtab_method->lookup(name);
auto cur_method = classtable->symtab_method_lookup_parent(method_env_class, this->name);
if (cur_method == nullptr) {
if (semant_debug) {
std::cerr << "lookup method " << this->name << " in class " << method_env_class << "\n";
}
classtable->semant_error(cur_class->get_filename(), this)
<< "Dispatch to undefined method " << name
<< ".\n";
this->type = Object;
return Object;
}
if (actual->len() != cur_method->get_formals()->len()) {
classtable->semant_error(cur_class->get_filename(), this)
<< " Method " << name
<< "Method " << name
<< " called with wrong number of arguments.\n";
this->type = Object;
return Object;
}
auto formals = cur_method->get_formals();
auto formals = cur_method->get_formals(); // T_i'
auto _param_type_iter = _param_type.begin();
for (auto i = formals->first(); formals->more(i); i = formals->next(i)) {
for (auto i = formals->first();
formals->more(i);
i = formals->next(i), ++_param_type_iter)
{
auto formal_i = static_cast<formal_class*>(formals->nth(i));
if (!classtable->conform(*_param_type_iter, formal_i->get_type_decl())) {
auto formal_i_type = formal_i->get_type_decl();
if (!classtable->conform_self(*_param_type_iter, formal_i_type, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "In call of method " << cur_method->get_name()
<< ", type " << *_param_type_iter
@ -783,9 +880,9 @@ Symbol dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
<< " does not conform to declared type " << formal_i->get_type_decl()
<< ".\n";
}
++_param_type_iter;
}
auto return_type = cur_method->get_return_type();
auto return_type = cur_method->get_return_type(); // T_n+1
if (return_type == SELF_TYPE) {
return_type = expr_type;
}
@ -851,7 +948,7 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
_existed_type.insert(type_decl_i);
}
else {
classtable->semant_error(cur_class->get_filename(), this)
classtable->semant_error(cur_class->get_filename(), branch_i)
<< "Duplicate branch " << type_decl_i
<< " in case statement.\n";
}
@ -861,12 +958,12 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
for later expr typing
*/
if (type_decl_i == SELF_TYPE) {
classtable->semant_error(cur_class->get_filename(), this)
classtable->semant_error(cur_class->get_filename(), branch_i)
<< "Identifier " << name_i
<< " declared with type SELF_TYPE in case branch.\n";
}
else if (!classtable->class_exist(type_decl_i)) {
classtable->semant_error(cur_class->get_filename(), this)
classtable->semant_error(cur_class->get_filename(), branch_i)
<< "Class " << type_decl_i
<< " of case branch is undefined.\n";
}
@ -911,16 +1008,19 @@ Symbol block_class::semant(Class_ cur_class, ClassTable* classtable)
*/
Symbol let_class::semant(Class_ cur_class, ClassTable* classtable)
{
if (!classtable->class_exist(type_decl)) {
if (this->identifier == self) {
classtable->semant_error(cur_class->get_filename(), this)
<< "\'self\' cannot be bound in a \'let\' expression.\n";
}
if (!classtable->class_exist_self(type_decl)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Class " << type_decl
<< " of attribute " << identifier
<< " of let-bound identifier " << identifier
<< " is undefined.\n";
this->type_decl = Object;
}
if (typeid(*init) != typeid(no_expr_class)) {
auto init_type = init->semant(cur_class, classtable);
if (!classtable->conform(init_type, type_decl)) {
if (!classtable->conform_self(init_type, type_decl, cur_class)) {
classtable->semant_error(cur_class->get_filename(), this)
<< "Inferred type " << init_type
<< " of initialization of " << identifier
@ -1148,13 +1248,13 @@ Symbol string_const_class::semant(Class_ cur_class, ClassTable* classtable)
*/
Symbol new__class::semant(Class_ cur_class, ClassTable* classtable)
{
if (classtable->class_exist(this->type_name)) {
if (classtable->class_exist_self(this->type_name)) {
this->type = this->type_name;
}
else {
classtable->semant_error(cur_class->get_filename(), this)
<< "\'new\' used with undefined class " << this->type_name
<< "\n";
<< ".\n";
this->type = Object;
}
return this->type;
@ -1167,14 +1267,18 @@ Symbol new__class::semant(Class_ cur_class, ClassTable* classtable)
Symbol isvoid_class::semant(Class_ cur_class, ClassTable* classtable)
{
auto _ = this->e1->semant(cur_class, classtable);
this->type = Bool;
return Bool;
}
/*
* NoExpr:
* `no_expr` always has type `_no_type`
* However, this class should never be visited during type checking
*/
Symbol no_expr_class::semant(Class_ cur_class, ClassTable* classtable)
{
assert(0);
return No_type;
}
@ -1185,14 +1289,19 @@ Symbol no_expr_class::semant(Class_ cur_class, ClassTable* classtable)
*/
Symbol object_class::semant(Class_ cur_class, ClassTable* classtable)
{
auto object_type = classtable->symtab_obj(cur_class)->lookup(name);
auto object_type = classtable->symtab_object_lookup_parent(cur_class, name);
if (object_type != nullptr) {
this->type = object_type;
return object_type;
}
else {
if (semant_debug) {
std::cerr << "Cannot find " << name << " in Class " << classtable->class_to_name(cur_class) << "\n";
classtable->symtab_obj(cur_class)->dump();
std::cerr << "-------------------\n";
}
classtable->semant_error(cur_class->get_filename(), this)
<< "Undeclared identifier " << name<< "\n";
<< "Undeclared identifier " << name<< ".\n";
this->type = Object;
return Object;
}

View File

@ -156,23 +156,36 @@ public:
/* helpers */
void install_all_features();
void symtab_dump(Symbol);
Symbol symtab_object_lookup_parent(Symbol, Symbol);
method_class* symtab_method_lookup_parent(Symbol, Symbol);
Symbol symtab_object_lookup_parent(Symbol, Symbol) const;
Symbol symtab_object_lookup_parent(Class_, Symbol) const;
method_class* symtab_method_lookup_parent(Symbol, Symbol) const;
method_class* symtab_method_lookup_parent(Class_, Symbol) const;
bool conform(Symbol, Symbol) const;
bool conform_self(Symbol, Symbol, Symbol) const;
bool conform_self(Symbol, Symbol, Class_) const;
bool class_exist(Symbol) const;
bool class_exist_self(Symbol) const;
Symbol lub(Symbol, Symbol) const;
Symbol lub(Symbol, Symbol, Symbol) const;
static Symbol class_to_name(Class_ class_item) { return static_cast<class__class*>(class_item)->get_name(); }
/* wrappers */
std::vector<class__class*>& class_vec() { return _class_vec; }
SymbolTable<Symbol, Entry>* symtab_obj(Class_ class_i) {
SymbolTable<Symbol, Entry>* symtab_obj(Class_ class_i) const {
auto class_id = static_cast<class__class*>(class_i)->get_name();
return _symtab_obj[class_id];
auto _iter = _symtab_obj.find(class_id);
if (_iter == _symtab_obj.end()) return nullptr;
return _iter->second;
};
SymbolTable<Symbol, method_class>* symtab_met(Class_ class_i) {
SymbolTable<Symbol, method_class>* symtab_met(Class_ class_i) const {
auto class_id = static_cast<class__class*>(class_i)->get_name();
return _symtab_met[class_id];
auto _iter = _symtab_met.find(class_id);
if (_iter == _symtab_met.end()) return nullptr;
return _iter->second;
};
SymbolTable<Symbol, method_class>* symtab_met(Symbol class_id) {
return _symtab_met[class_id];
SymbolTable<Symbol, method_class>* symtab_met(Symbol class_id) const {
auto _iter = _symtab_met.find(class_id);
if (_iter == _symtab_met.end()) return nullptr;
return _iter->second;
};
int errors() { return semant_errors; }