Add initial parsing for let construct
This commit is contained in:
parent
a19caf4fe6
commit
d1eb4befcc
13
PFunction.cc
13
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
|
* 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
29
PTask.h
|
|
@ -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
58
parse.y
|
|
@ -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
|
||||||
|
|
|
||||||
40
pform.cc
40
pform.cc
|
|
@ -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
12
pform.h
|
|
@ -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 ¶m_signed,
|
bool ¶m_signed,
|
||||||
ivl_variable_type_t ¶m_type);
|
ivl_variable_type_t ¶m_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.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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_ << "; /* "
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue