@@ -7,68 +7,73 @@ namespace intp::interp {
77 static NativeFunction make_print () {
88 const std::string name = " print" ;
99 return {
10- -1 , name, [](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
10+ -1 , name, [](const std::vector<std::shared_ptr<Thunk> > &args,
11+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
1112 for (auto &arg: args) {
1213 const Value &value = arg->force ();
1314 std::cout << value;
1415 }
15- return Value{static_cast <double >(0 )};
16+ return std::make_pair ( Value{static_cast <double >(0 )}, ResultOptions{. side_effects = true }) ;
1617 }
1718 };
1819 }
1920
2021 static NativeFunction make_add () {
2122 const std::string name = " add" ;
2223 return {
23- 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
24+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
25+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
2426 const Value &value1 = args[0 ]->force ();
2527 const Value &value2 = args[1 ]->force ();
2628 if (!std::holds_alternative<double >(value1) || !std::holds_alternative<double >(value2)) {
2729 options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
2830 " \n " , name, " signature: Float -> Float -> Float" );
2931 }
3032 const double result = std::get<double >(value1) + std::get<double >(value2);
31- return Value{result};
33+ return std::make_pair ( Value{result}, ResultOptions{}) ;
3234 }
3335 };
3436 }
3537
3638 static NativeFunction make_sub () {
3739 const std::string name = " sub" ;
3840 return {
39- 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
41+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
42+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
4043 const Value &value1 = args[0 ]->force ();
4144 const Value &value2 = args[1 ]->force ();
4245 if (!std::holds_alternative<double >(value1) || !std::holds_alternative<double >(value2)) {
4346 options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
4447 " \n " , name, " signature: Float -> Float -> Float" );
4548 }
4649 const double result = std::get<double >(value1) - std::get<double >(value2);
47- return Value{result};
50+ return std::make_pair ( Value{result}, ResultOptions{}) ;
4851 }
4952 };
5053 }
5154
5255 static NativeFunction make_mul () {
5356 const std::string name = " mul" ;
5457 return {
55- 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
58+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
59+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
5660 const Value &value1 = args[0 ]->force ();
5761 const Value &value2 = args[1 ]->force ();
5862 if (!std::holds_alternative<double >(value1) || !std::holds_alternative<double >(value2)) {
5963 options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
6064 " \n " , name, " signature: Float -> Float -> Float" );
6165 }
6266 const double result = std::get<double >(value1) * std::get<double >(value2);
63- return Value{result};
67+ return std::make_pair ( Value{result}, ResultOptions{}) ;
6468 }
6569 };
6670 }
6771
6872 static NativeFunction make_cmp () {
6973 const std::string name = " cmp" ;
7074 return {
71- 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
75+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
76+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
7277 const Value &value1 = args[0 ]->force ();
7378 const Value &value2 = args[1 ]->force ();
7479 if (!std::holds_alternative<double >(value1) || !std::holds_alternative<double >(value2)) {
@@ -78,15 +83,16 @@ namespace intp::interp {
7883 const double num1 = std::get<double >(value1);
7984 const double num2 = std::get<double >(value2);
8085 const int result = num1 < num2 ? -1 : num1 > num2 ? 1 : 0 ;
81- return Value{static_cast <double >(result)};
86+ return std::make_pair ( Value{static_cast <double >(result)}, ResultOptions{}) ;
8287 }
8388 };
8489 }
8590
8691 static NativeFunction make_if_zero () {
8792 const std::string name = " if_zero" ;
8893 return {
89- 3 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
94+ 3 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
95+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
9096 const Value &cond_value = args[0 ]->force ();
9197 if (!std::holds_alternative<double >(cond_value)) {
9298 options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
@@ -96,9 +102,9 @@ namespace intp::interp {
96102 }
97103 // Lazy branching: only force the chosen clause
98104 if (const double cond = std::get<double >(cond_value); cond == 0.0 ) {
99- return args[1 ]->force ();
105+ return std::make_pair (Value{ args[1 ]->force ()}, ResultOptions{} );
100106 }
101- return args[2 ]->force ();
107+ return std::make_pair (Value{ args[2 ]->force ()}, ResultOptions{} );
102108 }
103109 };
104110 }
@@ -108,8 +114,9 @@ namespace intp::interp {
108114 }
109115
110116 static Value list_get (const std::shared_ptr<List> &list_v, size_t index) {
111- if (index >= list_v->elements .size ())
112- throw std::out_of_range (" list index out of range" );
117+ if (index >= list_v->elements .size ()) {
118+ options_v.logger .error ({}, " runtime error: list index out of range, index is " , index);
119+ }
113120 return list_v->elements [index];
114121 }
115122
@@ -120,20 +127,66 @@ namespace intp::interp {
120127 static NativeFunction make_list () {
121128 const std::string name = " list" ;
122129 return {
123- -1 , name, [](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
130+ -1 , name, [](const std::vector<std::shared_ptr<Thunk> > &args,
131+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
124132 std::vector<Value> values;
125133 for (auto &arg: args) {
126134 values.push_back (arg->force ());
127135 }
128- return make_list_obj (values);
136+ return std::make_pair (Value{make_list_obj (values)}, ResultOptions{});
137+ }
138+ };
139+ }
140+
141+ static NativeFunction make_list_size () {
142+ const std::string name = " list_size" ;
143+ return {
144+ 1 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
145+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
146+ const Value &arg0 = args[0 ]->force ();
147+ if (!std::holds_alternative<std::shared_ptr<List> >(arg0)) {
148+ options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
149+ " \n " , name,
150+ " signature: List -> Float" " \n "
151+ " runtime error: expected <List> got " , arg0);
152+ }
153+ const auto list_v = std::get<std::shared_ptr<List> >(arg0);
154+ return std::make_pair (Value{static_cast <double >(list_v->elements .size ())}, ResultOptions{});
155+ }
156+ };
157+ }
158+
159+ static NativeFunction make_list_get () {
160+ const std::string name = " list_get" ;
161+ return {
162+ // TODO: Add type checker to replace this manual approach
163+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
164+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
165+ const Value &arg0 = args[0 ]->force ();
166+ if (!std::holds_alternative<std::shared_ptr<List> >(arg0)) {
167+ options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
168+ " \n " , name,
169+ " signature: List -> Float -> List" " \n "
170+ " runtime error: expected <List> got " , arg0);
171+ }
172+ const Value &arg1 = args[1 ]->force ();
173+ if (!std::holds_alternative<double >(arg1)) {
174+ options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
175+ " \n " , name,
176+ " signature: List -> Float -> List" " \n "
177+ " runtime error: expected <Float> got " , arg1);
178+ }
179+ return std::make_pair (Value{list_get (std::get<std::shared_ptr<List> >(arg0), std::get<double >(arg1))},
180+ ResultOptions{});
129181 }
130182 };
131183 }
132184
133185 static NativeFunction make_list_append () {
134186 const std::string name = " list_append" ;
135187 return {
136- 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args, const std::shared_ptr<Env> &) -> Value {
188+ 2 , name, [name](const std::vector<std::shared_ptr<Thunk> > &args,
189+ const std::shared_ptr<Env> &) -> std::pair<Value, ResultOptions> {
137190 const Value &arg0 = args[0 ]->force ();
138191 if (!std::holds_alternative<std::shared_ptr<List> >(arg0)) {
139192 options_v.logger .error ({}, " runtime error: wrong arguments provided to native function " , name,
@@ -143,7 +196,7 @@ namespace intp::interp {
143196 }
144197 auto list_v = std::get<std::shared_ptr<List> >(arg0);
145198 list_append (list_v, args[1 ]->force ());
146- return list_v;
199+ return std::make_pair (Value{ list_v}, ResultOptions{}) ;
147200 }
148201 };
149202 }
@@ -158,6 +211,8 @@ namespace intp::interp {
158211 {make_cmp ()},
159212 {make_if_zero ()},
160213 {make_list ()},
214+ {make_list_size ()},
215+ {make_list_get ()},
161216 {make_list_append ()}
162217 };
163218 }
0 commit comments