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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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; 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 #ifndef IVL_PTask_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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_; 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 */ #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; LexicalScope::range_t* value_range;
vector<Module::port_t*>*mports; 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; named_number_t* named_number;
list<named_number_t>* named_numbers; 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 <gate> gate_instance
%type <gates> gate_instance_list %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 <pform_name> hierarchy_identifier implicit_class_handle
%type <expr> assignment_pattern expression expr_mintypmax %type <expr> assignment_pattern expression expr_mintypmax
%type <expr> expr_primary_or_typename expr_primary %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> inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation %type <expr> branch_probe_expression streaming_concatenation
%type <expr> delay_value delay_value_simple %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 <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> 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 <class_type> class_identifier
%type <struct_member> struct_union_member %type <struct_member> struct_union_member
%type <struct_members> struct_union_member_list %type <struct_members> struct_union_member_list
@ -5169,6 +5174,11 @@ module_item
yyerrok; 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 /* Maybe this is a discipline declaration? If so, then the lexor
will see the discipline name as an identifier. We match it to the will see the discipline name as an identifier. We match it to the
discipline or type name semantically. */ 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_list module_item : module_item_list module_item
| 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; << data_type->get_fileline() << "." << endl;
error_count += 1; 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. * Specify paths.
*/ */

12
pform.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_H #ifndef IVL_pform_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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, bool &param_signed,
ivl_variable_type_t &param_type); 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. * 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; 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 void PRelease::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << "" << "release " << *lval_ << "; /* " out << setw(ind) << "" << "release " << *lval_ << "; /* "