1 // Copyright 2016-2021 Doug Moen
2 // Licensed under the Apache License, version 2.0
3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0
4 
5 #include <libcurv/module.h>
6 #include <libcurv/function.h>
7 #include <libcurv/exception.h>
8 
9 namespace curv {
10 
11 const char Module_Base::name[] = "module";
12 
13 void
print_repr(std::ostream & out) const14 Module_Base::print_repr(std::ostream& out) const
15 {
16     out << "{";
17     bool first = true;
18     for (auto i : *this) {
19         if (!first) out << ",";
20         first = false;
21         out << i.first << ":";
22         i.second.print_repr(out);
23     }
24     out << "}";
25 }
26 
27 Value
get(slot_t i) const28 Module_Base::get(slot_t i) const
29 {
30     Value val = array_[i];
31     // A recursive function is represented by a Closure, whose nonlocals_
32     // member is a Module that contains Lambda objects wherever there is a
33     // recursive function reference. This code converts those Lambda objects
34     // into proper Values. (This is a trick to avoid reference cycles in the
35     // representation of function values, which would break reference counting.)
36     if (val.is_ref()) {
37         auto& ref = val.to_ref_unsafe();
38         if (ref.type_ == Ref_Value::ty_lambda)
39             return {make<Closure>((Lambda&)ref, *(Module*)this)};
40     }
41     return val;
42 }
43 
44 Value
find_field(Symbol_Ref name,const Context & cx) const45 Module_Base::find_field(Symbol_Ref name, const Context& cx) const
46 {
47     auto b = dictionary_->find(name);
48     if (b != dictionary_->end())
49         return get(b->second);
50     return missing;
51 }
52 
53 bool
hasfield(Symbol_Ref name) const54 Module_Base::hasfield(Symbol_Ref name) const
55 {
56     auto b = dictionary_->find(name);
57     return (b != dictionary_->end());
58 }
59 
60 Shared<Record>
clone() const61 Module_Base::clone() const
62 {
63     return Module::make_copy(&array_[0], size(), dictionary_);
64 }
65 
66 Value*
ref_field(Symbol_Ref name,bool need_value,const Context & cx)67 Module_Base::ref_field(Symbol_Ref name, bool need_value, const Context& cx)
68 {
69     auto b = dictionary_->find(name);
70     // WARNING: array_[i] can be a Closure, which is not a proper value.
71     if (b != dictionary_->end())
72         return &array_[b->second];
73     throw Exception(cx, stringify(Value{share(*this)},
74         " has no field named ", name));
75 }
76 
77 } // namespace curv
78