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