M include/scopes/scopes.h +22 -0
@@ 56,6 56,7 @@ namespace scopes {
struct Frame;
struct Value;
struct Closure;
+ struct Block;
}
extern "C" {
@@ 73,6 74,8 @@ typedef scopes::Closure sc_closure_t;
typedef scopes::ValueRef sc_valueref_t;
+typedef scopes::Block sc_block_t;
+
// some of the return types are technically illegal in C, but we take care
// that the alignment is correct
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
@@ 92,6 95,8 @@ typedef struct sc_closure_ sc_closure_t;
typedef struct sc_valueref_ { sc_value_t *_0; const sc_anchor_t *_1; } sc_valueref_t;
+typedef struct sc_block_ sc_block_t;
+
#endif
// aliasing uint64_t to a struct with a single uint64_t member is UB, and hasn't
@@ 534,6 539,23 @@ SCOPES_LIBEXPORT const sc_type_t *sc_ima
SCOPES_LIBEXPORT const sc_type_t *sc_sampled_image_type(const sc_type_t *_type);
+// inspect API
+
+// Function
+SCOPES_LIBEXPORT sc_block_t *sc_function_get_body(sc_valueref_t fn);
+
+// Block
+SCOPES_LIBEXPORT int sc_block_instruction_count(sc_block_t *block);
+SCOPES_LIBEXPORT sc_valueref_t sc_block_get_instruction(sc_block_t *block, int index);
+SCOPES_LIBEXPORT sc_valueref_t sc_block_terminator(sc_block_t *block);
+
+// Call
+SCOPES_LIBEXPORT sc_valueref_t sc_icall_callee(sc_valueref_t value);
+SCOPES_LIBEXPORT int sc_icall_argcount(sc_valueref_t value);
+SCOPES_LIBEXPORT sc_valueref_t sc_icall_getarg(sc_valueref_t value, int index);
+SCOPES_LIBEXPORT sc_block_t *sc_icall_exception_body(sc_valueref_t value);
+SCOPES_LIBEXPORT sc_type_raises_t sc_icall_exception_type(sc_valueref_t value);
+
#if defined __cplusplus
}
#endif
M lib/scopes/inspect.sc +28 -0
@@ 1,7 1,35 @@
+inline block-generator (self)
+ count := sc_block_instruction_count self
+ Generator
+ inline () 0
+ inline (i) (i < count)
+ inline (i) (sc_block_get_instruction self i)
+ inline (i) (+ i 1)
+
+type+ SCILBlock
+ inline __imply (cls T)
+ static-if (T == Generator) block-generator
+
+ __countof := sc_block_instruction_count
+ terminator := sc_block_terminator
+type+ Value
+ inline icall-args (self)
+ count := sc_icall_argcount self
+ Generator
+ inline () 0
+ inline (i) (i < count)
+ inline (i) (sc_icall_getarg self i)
+ inline (i) (+ i 1)
+ function-get-body := sc_function_get_body
+ icall-callee := sc_icall_callee
+ icall-argcount := sc_icall_argcount
+ icall-getarg := sc_icall_getarg
+ icall-exception-body := sc_icall_exception_body
+ icall-exception-type := sc_icall_exception_type
do
locals;
M src/error.hpp +2 -0
@@ 497,6 497,8 @@ formatters:
T(RTTypeBitcountMismatch, \
"runtime: provided word count (%1) does not match word count of type %0 (%2)", \
PType, int, int) \
+ T(RTUndefinedAttribute, \
+ "runtime: undefined attribute") \
// main
#define SCOPES_MAIN_ERROR_KIND() \
M src/globals.cpp +73 -0
@@ 2400,6 2400,67 @@ const sc_type_t *sc_sampled_image_type(c
return sampled_image_type(cast<ImageType>(_type));
}
+// Inspect API
+////////////////////////////////////////////////////////////////////////////////
+
+// Function
+////////////////////////////////////////////////////////////////////////////////
+
+sc_block_t *sc_function_get_body(sc_valueref_t fn) {
+ using namespace scopes;
+ return &fn.cast<Function>()->body;
+}
+
+// Block
+////////////////////////////////////////////////////////////////////////////////
+
+int sc_block_instruction_count(sc_block_t *block) {
+ assert(block);
+ return block->body.size();
+}
+
+sc_valueref_t sc_block_get_instruction(sc_block_t *block, int index) {
+ assert(block);
+ return block->body[index];
+}
+
+sc_valueref_t sc_block_terminator(sc_block_t *block) {
+ assert(block);
+ return block->terminator;
+}
+
+// Call
+////////////////////////////////////////////////////////////////////////////////
+
+sc_valueref_t sc_icall_callee(sc_valueref_t value) {
+ using namespace scopes;
+ return value.cast<Call>()->callee;
+}
+
+int sc_icall_argcount(sc_valueref_t value) {
+ using namespace scopes;
+ return value.cast<Call>()->args.size();
+}
+
+sc_valueref_t sc_icall_getarg(sc_valueref_t value, int index) {
+ using namespace scopes;
+ return value.cast<Call>()->args[index];
+}
+
+sc_block_t *sc_icall_exception_body(sc_valueref_t value) {
+ using namespace scopes;
+ return &value.cast<Call>()->except_body;
+}
+
+sc_type_raises_t sc_icall_exception_type(sc_valueref_t value) {
+ using namespace scopes;
+ SCOPES_RESULT_TYPE(const Type *);
+ auto exc = value.cast<Call>()->except;
+ if (!exc) {
+ SCOPES_C_ERROR(RTUndefinedAttribute);
+ }
+ SCOPES_C_RETURN(exc->get_type());
+}
} // extern "C"
@@ 2752,6 2813,18 @@ void init_globals(int argc, char *argv[]
DEFINE_RAISING_EXTERN_C_FUNCTION(sc_parse_from_path, TYPE_ValueRef, TYPE_String);
DEFINE_RAISING_EXTERN_C_FUNCTION(sc_parse_from_string, TYPE_ValueRef, TYPE_String);
+ DEFINE_EXTERN_C_FUNCTION(sc_function_get_body, TYPE_Block, TYPE_ValueRef);
+
+ DEFINE_EXTERN_C_FUNCTION(sc_block_instruction_count, TYPE_I32, TYPE_Block);
+ DEFINE_EXTERN_C_FUNCTION(sc_block_get_instruction, TYPE_ValueRef, TYPE_Block, TYPE_I32);
+ DEFINE_EXTERN_C_FUNCTION(sc_block_terminator, TYPE_ValueRef, TYPE_Block);
+
+ DEFINE_EXTERN_C_FUNCTION(sc_icall_callee, TYPE_ValueRef, TYPE_ValueRef);
+ DEFINE_EXTERN_C_FUNCTION(sc_icall_argcount, TYPE_I32, TYPE_ValueRef);
+ DEFINE_EXTERN_C_FUNCTION(sc_icall_getarg, TYPE_ValueRef, TYPE_ValueRef, TYPE_I32);
+ DEFINE_EXTERN_C_FUNCTION(sc_icall_exception_body, TYPE_Block, TYPE_ValueRef);
+ DEFINE_RAISING_EXTERN_C_FUNCTION(sc_icall_exception_type, TYPE_Type, TYPE_ValueRef);
+
#undef DEFINE_EXTERN_C_FUNCTION
#ifdef SCOPES_WIN32
M src/type.cpp +2 -0
@@ 569,6 569,8 @@ void init_types() {
DEFINE_OPAQUE_HANDLE_TYPE("Anchor", Anchor, TYPE_Anchor, nullptr);
+ DEFINE_OPAQUE_HANDLE_TYPE("SCILBlock", Block, TYPE_Block, nullptr);
+
DEFINE_BASIC_TYPE("Value", ValueRef, TYPE_ValueRef, nullptr,
tuple_type({ TYPE__Value, TYPE_Anchor }).assert_ok());
M src/type.hpp +3 -0
@@ 155,6 155,9 @@ typedef std::vector<const Type *> Types;
\
T(TYPE_Sampler, "Sampler") \
\
+ /* inspect API */ \
+ T(TYPE_Block, "SCILBlock") \
+ \
/* supertypes */ \
T(TYPE_Immutable, "immutable") \
T(TYPE_Aggregate, "aggregate") \
M testing/test_inspect.sc +18 -2
@@ 6,15 6,31 @@ import inspect
# test introspection
fn somefunc (a b)
+ print "somefunc called"
if a
return 1
else
return b
somefunc := `[(static-typify somefunc bool i32)]
-
assert ((tostring ('kind somefunc)) == "Function")
-
assert ((tostring ('kind i32)) == "IntegerType")
+block := 'function-get-body somefunc
+
+for instr in block
+ print ('kind instr)
+ switch ('kind instr)
+ case ValueKind.Call
+ print " " ('icall-callee instr)
+ for arg in ('icall-args instr)
+ print " " arg
+ print (countof ('icall-exception-body instr))
+ try
+ print ('icall-exception-type instr)
+ except (e)
+ print "no exception type"
+ default;
+print ('kind ('terminator block))
+
;
No newline at end of file