Add initial parsing for let construct

This commit is contained in:
Cary R 2021-01-18 13:01:23 -08:00
parent a19caf4fe6
commit d1eb4befcc
6 changed files with 174 additions and 5 deletions

View File

@ -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<let_port_t*>*ports,
PExpr*expr)
: PTaskFunc(name, parent), ports_(ports), expr_(expr)
{
}
PLet::~PLet()
{
}

29
PTask.h
View File

@ -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<pform_range_t>*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<let_port_t*>*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<let_port_t*>*ports_;
PExpr*expr_;
};
#endif /* IVL_PTask_H */

58
parse.y
View File

@ -394,6 +394,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
LexicalScope::range_t* value_range;
vector<Module::port_t*>*mports;
list<PLet::let_port_t*>*let_port_lst;
PLet::let_port_t*let_port_itm;
named_number_t* named_number;
list<named_number_t>* named_numbers;
@ -613,11 +616,13 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <gate> gate_instance
%type <gates> gate_instance_list
%type <let_port_lst> let_port_list_opt let_port_list
%type <let_port_itm> let_port_item
%type <pform_name> hierarchy_identifier implicit_class_handle
%type <expr> assignment_pattern expression expr_mintypmax
%type <expr> expr_primary_or_typename expr_primary
%type <expr> class_new dynamic_array_new
%type <expr> class_new dynamic_array_new let_default_opt
%type <expr> inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation
%type <expr> delay_value delay_value_simple
@ -629,7 +634,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <decl_assignments> list_of_variable_decl_assignments
%type <data_type> data_type data_type_or_implicit data_type_or_implicit_or_void
%type <data_type> simple_type_or_string
%type <data_type> simple_type_or_string let_formal_type
%type <class_type> class_identifier
%type <struct_member> struct_union_member
%type <struct_members> 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<PLet::let_port_t*>*tmp = new list<PLet::let_port_t*>;
tmp->push_back($1);
$$ = tmp;
}
| let_port_list ',' let_port_item
{ list<PLet::let_port_t*>*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

View File

@ -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<PLet::let_port*>*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<pform_range_t>*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.
*/

12
pform.h
View File

@ -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 &param_signed,
ivl_variable_type_t &param_type);
extern void pform_make_let(const struct vlltype&loc,
perm_string name,
list<PLet::let_port_t*>*ports,
PExpr*expr);
extern PLet::let_port_t* pform_make_let_port(data_type_t*data_type,
perm_string name,
list<pform_range_t>*range,
PExpr*def);
/*
* Functions related to specify blocks.
*/

View File

@ -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<let_port_t*>::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_ << "; /* "