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 #ifndef LIBCURV_SC_FRAME_H
6 #define LIBCURV_SC_FRAME_H
7 
8 #include <ostream>
9 #include <libcurv/sc_type.h>
10 #include <libcurv/module.h>
11 #include <libcurv/tail_array.h>
12 
13 namespace curv {
14 
15 struct Context;
16 struct SC_Compiler;
17 struct Phrase;
18 struct Function;
19 
20 /// An SSA variable used during SC code generation.
21 struct SC_Value
22 {
23     unsigned index;
24     SC_Type type;
25 
SC_ValueSC_Value26     SC_Value(unsigned i, SC_Type t) : index(i), type(t) {}
SC_ValueSC_Value27     SC_Value() noexcept {}
28 };
29 
30 /// print the GLSL variable name
31 inline std::ostream& operator<<(std::ostream& out, SC_Value v)
32 {
33     out << "r" << v.index;
34     return out;
35 }
36 
37 struct SC_Frame_Base;
38 using SC_Frame = Tail_Array<SC_Frame_Base>;
39 
40 /// A function call frame used by the Shape Compiler.
41 ///
42 /// The SC compilation process is a kind of abstract evaluation.
43 /// That's really clear when you see that SC_Frame is isomorphic to Frame,
44 /// with local slot Values replaced by SC_Values.
45 struct SC_Frame_Base
46 {
47     SC_Compiler& sc_;
48 
49     /// The root frame has a context pointer, which points to the shape
50     /// expression that is being compiled. Used for printing a stack trace.
51     const Context* root_context_;
52 
53     /// Frames are linked into a stack. This is metadata used for printing
54     /// a stack trace and by the debugger. It is not used during evaluation.
55     SC_Frame* parent_frame_;
56 
57     /// If this is a function call frame, then call_phrase_ is the source code
58     /// for the function call. If it is a frame for a reactive value expression,
59     /// then it's source code for the expression. Otherwise it's nullptr.
60     /// If not null, then the phrase creates a stack trace entry.
61     Shared<const Phrase> call_phrase_;
62 
63     // If this is a function call frame, then `func_` is the function that
64     // was called. Otherwise, nullptr. Used to print stack traces.
65     Shared<const Function> func_;
66 
67     /// Slot array containing the values of nonlocal bindings.
68     ///
69     /// This is:
70     /// * the slot array of a Closure value, for a function call frame
71     /// * nullptr, for a call to a builtin function.
72     Module* nonlocals_;
73 
74     // Tail array, containing the slots used for local bindings:
75     // function arguments, block bindings and other local, temporary values.
76     using value_type = SC_Value;
77     size_t size_;
78     value_type array_[0];
79 
80     SC_Value& operator[](size_t i)
81     {
82         assert(i < size_);
83         return array_[i];
84     }
85 
SC_Frame_BaseSC_Frame_Base86     SC_Frame_Base(
87         SC_Compiler& sc,
88         const Context* cx,
89         SC_Frame* parent,
90         Shared<const Function> func,
91         Shared<const Phrase> src)
92     :
93         sc_(sc),
94         root_context_(cx),
95         parent_frame_(parent),
96         call_phrase_(move(src)),
97         func_(move(func)),
98         nonlocals_(nullptr)
99     {}
100 };
101 
102 } // namespace
103 #endif // header guard
104