diff --git a/PFunction.cc b/PFunction.cc index 435e99f85..0cdde0e2d 100644 --- a/PFunction.cc +++ b/PFunction.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -89,3 +89,14 @@ PNamedItem::SymbolType PFunction::symbol_type() const { return FUNCTION; } + + +PLet::PLet(perm_string name, LexicalScope*parent, list*ports, + PExpr*expr) +: PTaskFunc(name, parent), ports_(ports), expr_(expr) +{ +} + +PLet::~PLet() +{ +} diff --git a/PTask.h b/PTask.h index 1d328ed6c..10a3206c5 100644 --- a/PTask.h +++ b/PTask.h @@ -1,7 +1,7 @@ #ifndef IVL_PTask_H #define IVL_PTask_H /* - * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -158,4 +158,31 @@ class PFunction : public PTaskFunc { bool is_auto_; }; +// A let is like a simple function that is expanded in the compiler +class PLet : public PTaskFunc { + public: + typedef struct let_port { + data_type_t*type_; + perm_string name_; + list*range_; + PExpr*def_; + + void dump(ostream&, unsigned) const; + } let_port_t; + +// FIXME: Should the port list be a vector. Check once implemented completely + explicit PLet(perm_string name, LexicalScope*parent, + list*ports, PExpr*expr); + ~PLet(); + + void elaborate_sig(Design*des, NetScope*scope) const { (void)des; (void)scope; } + void elaborate(Design*des, NetScope*scope) const { (void)des; (void)scope; } + + void dump(ostream&, unsigned) const; + + private: + list*ports_; + PExpr*expr_; +}; + #endif /* IVL_PTask_H */ diff --git a/parse.y b/parse.y index c7db3ace6..6f7787c4f 100644 --- a/parse.y +++ b/parse.y @@ -394,6 +394,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector LexicalScope::range_t* value_range; vector*mports; + list*let_port_lst; + PLet::let_port_t*let_port_itm; + named_number_t* named_number; list* named_numbers; @@ -613,11 +616,13 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type gate_instance %type gate_instance_list +%type let_port_list_opt let_port_list +%type let_port_item %type hierarchy_identifier implicit_class_handle %type assignment_pattern expression expr_mintypmax %type expr_primary_or_typename expr_primary -%type class_new dynamic_array_new +%type class_new dynamic_array_new let_default_opt %type inc_or_dec_expression inside_expression lpvalue %type branch_probe_expression streaming_concatenation %type delay_value delay_value_simple @@ -629,7 +634,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type list_of_variable_decl_assignments %type data_type data_type_or_implicit data_type_or_implicit_or_void -%type simple_type_or_string +%type simple_type_or_string let_formal_type %type class_identifier %type struct_union_member %type struct_union_member_list @@ -5169,6 +5174,11 @@ module_item yyerrok; } + | K_let IDENTIFIER let_port_list_opt '=' expression ';' + { perm_string tmp2 = lex_strings.make($2); + pform_make_let(@1, tmp2, $3, $5); + } + /* Maybe this is a discipline declaration? If so, then the lexor will see the discipline name as an identifier. We match it to the discipline or type name semantically. */ @@ -5424,6 +5434,50 @@ module_item ; +let_port_list_opt + : '(' let_port_list ')' + { $$ = $2; } + | '(' ')' + { $$ = 0; } + | + { $$ = 0; } + ; + +let_port_list + : let_port_item + { list*tmp = new list; + tmp->push_back($1); + $$ = tmp; + } + | let_port_list ',' let_port_item + { list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } + ; + + // FIXME: What about the attributes? +let_port_item + : attribute_list_opt let_formal_type IDENTIFIER dimensions_opt let_default_opt + { perm_string tmp3 = lex_strings.make($3); + $$ = pform_make_let_port($2, tmp3, $4, $5); + } + ; + +let_default_opt + : '=' expression + { $$ = $2; } + | + { $$ = 0; } + ; + +let_formal_type + : data_type_or_implicit + { $$ = $1; } + | K_untyped + { $$ = 0; } + ; + module_item_list : module_item_list module_item | module_item diff --git a/pform.cc b/pform.cc index 9e7a95d86..0956c6455 100644 --- a/pform.cc +++ b/pform.cc @@ -3273,6 +3273,46 @@ void pform_set_param_from_type(const struct vlltype&loc, << data_type->get_fileline() << "." << endl; error_count += 1; } + +void pform_make_let(const struct vlltype&loc, + perm_string name, + list*ports, + PExpr*expr) +{ + LexicalScope*scope = pform_peek_scope(); + + cerr << loc.get_fileline() << ": sorry: let declarations (" + << name << ") are not currently supported." << endl; + error_count += 1; + + PLet*res = new PLet(name, scope, ports, expr); + FILE_NAME(res, loc); + +/* + cerr << "Found: "; + res->dump(cerr, 0); +*/ + + delete res; + delete ports; + delete expr; +} + +PLet::let_port_t* pform_make_let_port(data_type_t*data_type, + perm_string name, + list*range, + PExpr*def) +{ + PLet::let_port_t*res = new PLet::let_port_t; + + res->type_ = data_type; + res->name_ = name; + res->range_ = range; + res->def_ = def; + + return res; +} + /* * Specify paths. */ diff --git a/pform.h b/pform.h index 070f23829..200612764 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef IVL_pform_H #define IVL_pform_H /* - * Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -437,6 +437,16 @@ extern void pform_set_param_from_type(const struct vlltype&loc, bool ¶m_signed, ivl_variable_type_t ¶m_type); +extern void pform_make_let(const struct vlltype&loc, + perm_string name, + list*ports, + PExpr*expr); + +extern PLet::let_port_t* pform_make_let_port(data_type_t*data_type, + perm_string name, + list*range, + PExpr*def); + /* * Functions related to specify blocks. */ diff --git a/pform_dump.cc b/pform_dump.cc index 2538be1dd..bf306a4c1 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1144,6 +1144,33 @@ void PFunction::dump(ostream&out, unsigned ind) const out << setw(ind+2) << "" << "/* NOOP */" << endl; } +void PLet::let_port_t::dump(ostream&out, unsigned) const +{ + if (type_) out << *type_ << " "; + out << name_; + // FIXME: This has not been tested and is likely wrong! + if (range_) out << " " << range_; + if (def_) out << "=" << *def_; +} + +void PLet::dump(ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "let "; + out << pscope_name(); + if (ports_) { + out << "("; + typedef std::list::const_iterator port_itr_t; + port_itr_t idx = ports_->begin(); + (*idx)->dump(out, 0); + for (++idx; idx != ports_->end(); ++idx ) { + out << ", "; + (*idx)->dump(out, 0); + } + out << ")"; + } + out << " = " << *expr_ << ";" << endl; +} + void PRelease::dump(ostream&out, unsigned ind) const { out << setw(ind) << "" << "release " << *lval_ << "; /* "