use std::sync::Arc;
use crate::ast::Mode;
use crate::ast::ObjectClass;
use crate::data::Symbol;
use crate::syntax::Symbols;
use super::formal_region::FormalRegion;
use super::named_entity::Signature;
use super::region::NamedEntityKind;
use super::region::Object;
use super::region::Region;
use super::region::Subtype;
use super::region::TypeEnt;
use super::NamedEntity;
pub struct StandardRegion<'a> {
symbols: &'a Symbols,
region: &'a Region<'a>,
}
impl<'a> StandardRegion<'a> {
pub fn new(symbols: &'a Symbols, region: &'a Region<'a>) -> Self {
Self { symbols, region }
}
fn symbol(&self, name: &str) -> Symbol {
self.symbols.symtab().insert_utf8(name)
}
fn lookup_type(&self, name: &str) -> TypeEnt {
TypeEnt::from_any(
self.region
.lookup_immediate(&self.symbol(name).into())
.unwrap()
.clone()
.into_non_overloaded()
.unwrap(),
)
.unwrap()
}
fn string(&self) -> TypeEnt {
self.lookup_type("STRING")
}
fn boolean(&self) -> TypeEnt {
self.lookup_type("BOOLEAN")
}
fn natural(&self) -> TypeEnt {
self.lookup_type("NATURAL")
}
fn real(&self) -> TypeEnt {
self.lookup_type("REAL")
}
fn time(&self) -> TypeEnt {
self.lookup_type("TIME")
}
fn file_open_kind(&self) -> TypeEnt {
self.lookup_type("FILE_OPEN_KIND")
}
fn file_open_status(&self) -> TypeEnt {
self.lookup_type("FILE_OPEN_STATUS")
}
pub fn create_implicit_file_type_subprograms(
&self,
file_type: &TypeEnt,
type_mark: &TypeEnt,
) -> Vec<Arc<NamedEntity>> {
let mut implicit = Vec::new();
let string = self.string();
let boolean = self.boolean();
let file_open_kind = self.file_open_kind();
let file_open_status = self.file_open_status();
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("External_Name"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(string.clone()),
has_default: false,
}),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("Open_Kind"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(file_open_kind.clone()),
has_default: true,
}),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("FILE_OPEN"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("Status"),
NamedEntityKind::Object(Object {
class: ObjectClass::Variable,
mode: Some(Mode::Out),
subtype: Subtype::new(file_open_status),
has_default: false,
}),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("External_Name"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(string),
has_default: false,
}),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("Open_Kind"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(file_open_kind),
has_default: true,
}),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("FILE_OPEN"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("FILE_CLOSE"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Variable,
mode: Some(Mode::Out),
subtype: Subtype::new(type_mark.clone()),
has_default: false,
}),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("READ"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(type_mark.clone()),
has_default: false,
}),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("WRITE"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("FLUSH"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
file_type.decl_pos(),
)));
}
{
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("F"),
NamedEntityKind::InterfaceFile(file_type.to_owned()),
file_type.decl_pos(),
)));
implicit.push(Arc::new(NamedEntity::implicit(
file_type.clone().into(),
self.symbol("ENDFILE"),
NamedEntityKind::Subprogram(Signature::new(params, Some(boolean))),
file_type.decl_pos(),
)));
}
implicit
}
pub fn create_to_string(&self, type_ent: TypeEnt) -> Arc<NamedEntity> {
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(type_ent.to_owned()),
has_default: false,
}),
type_ent.decl_pos(),
)));
Arc::new(NamedEntity::implicit(
type_ent.clone().into(),
self.symbol("TO_STRING"),
NamedEntityKind::Subprogram(Signature::new(params, Some(self.string()))),
type_ent.decl_pos(),
))
}
fn create_min_or_maximum(&self, name: &str, type_ent: TypeEnt) -> Arc<NamedEntity> {
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("L"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(type_ent.to_owned()),
has_default: false,
}),
type_ent.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("R"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(type_ent.to_owned()),
has_default: false,
}),
type_ent.decl_pos(),
)));
Arc::new(NamedEntity::implicit(
type_ent.clone().into(),
self.symbol(name),
NamedEntityKind::Subprogram(Signature::new(params, Some(type_ent.clone()))),
type_ent.decl_pos(),
))
}
pub fn minimum(&self, type_ent: TypeEnt) -> Arc<NamedEntity> {
self.create_min_or_maximum("MINIMUM", type_ent)
}
pub fn maximum(&self, type_ent: TypeEnt) -> Arc<NamedEntity> {
self.create_min_or_maximum("MAXIMUM", type_ent)
}
pub fn create_deallocate(&self, type_ent: &TypeEnt) -> Arc<NamedEntity> {
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("P"),
NamedEntityKind::Object(Object {
class: ObjectClass::Variable,
mode: Some(Mode::InOut),
subtype: Subtype::new(type_ent.to_owned()),
has_default: false,
}),
type_ent.decl_pos(),
)));
Arc::new(NamedEntity::implicit(
type_ent.clone().into(),
self.symbol("DEALLOCATE"),
NamedEntityKind::Subprogram(Signature::new(params, None)),
type_ent.decl_pos(),
))
}
pub fn end_of_package_implicits(&self) -> Vec<Arc<NamedEntity>> {
let mut res = Vec::new();
for name in [
"BOOLEAN",
"BIT",
"CHARACTER",
"SEVERITY_LEVEL",
"INTEGER",
"REAL",
"TIME",
"FILE_OPEN_KIND",
"FILE_OPEN_STATUS",
] {
let typ = self.lookup_type(name);
let implicits = vec![
self.create_to_string(typ.clone()),
self.minimum(typ.clone()),
self.maximum(typ.clone()),
];
for ent in implicits.iter() {
if let Some(implicit) = typ.kind().implicits() {
unsafe { implicit.push(ent) };
}
}
res.extend(implicits);
}
{
let real = self.real();
let natural = self.natural();
let string = self.string();
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(real.to_owned()),
has_default: false,
}),
real.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("DIGITS"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(natural),
has_default: false,
}),
real.decl_pos(),
)));
let ent = Arc::new(NamedEntity::implicit(
real.clone().into(),
self.symbol("TO_STRING"),
NamedEntityKind::Subprogram(Signature::new(params, Some(string))),
real.decl_pos(),
));
if let Some(implicit) = real.kind().implicits() {
unsafe { implicit.push(&ent) };
}
res.push(ent);
}
{
let real = self.real();
let string = self.string();
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(real.to_owned()),
has_default: false,
}),
real.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("FORMAT"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(string.to_owned()),
has_default: false,
}),
real.decl_pos(),
)));
let ent = Arc::new(NamedEntity::implicit(
real.clone().into(),
self.symbol("TO_STRING"),
NamedEntityKind::Subprogram(Signature::new(params, Some(string))),
real.decl_pos(),
));
if let Some(implicit) = real.kind().implicits() {
unsafe { implicit.push(&ent) };
}
res.push(ent);
}
{
let time = self.time();
let string = self.string();
let mut params = FormalRegion::new_params();
params.add(Arc::new(NamedEntity::new(
self.symbol("VALUE"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(time.to_owned()),
has_default: false,
}),
time.decl_pos(),
)));
params.add(Arc::new(NamedEntity::new(
self.symbol("UNIT"),
NamedEntityKind::Object(Object {
class: ObjectClass::Constant,
mode: Some(Mode::In),
subtype: Subtype::new(time.to_owned()),
has_default: false,
}),
time.decl_pos(),
)));
let ent = Arc::new(NamedEntity::implicit(
time.clone().into(),
self.symbol("TO_STRING"),
NamedEntityKind::Subprogram(Signature::new(params, Some(string))),
time.decl_pos(),
));
if let Some(implicit) = time.kind().implicits() {
unsafe { implicit.push(&ent) };
}
res.push(ent);
}
res
}
}