xo-interpreter: apply expressions + llvm builtins working!

This commit is contained in:
Roland Conybeare 2025-11-28 19:32:56 -05:00
commit 1d1e72adf3
31 changed files with 531 additions and 50 deletions

View file

@ -3,6 +3,7 @@
* @author Roland Conybeare, Nov 2025
**/
#include "xo/object/ObjectConverter.hpp"
#include "xo/alloc/IAlloc.hpp"
#include "GlobalEnv.hpp"
@ -10,6 +11,21 @@ namespace xo {
namespace scm {
struct BuiltinPrimitives {
public:
using ObjectConverter = xo::obj::ObjectConverter;
/** install conversions for PrimitiveExpr<Fn> -> Primitive<Fn>
* for particular function pointer types Fn.
*
* Source type from xo-expression
* Dest type from xo-object.
*
* Module dependence goes the other way
* i.e. xo-interpreter -uses-> xo-expression
* -uses-> xo-object
* For this reason rejected adding a virtual method to PrimitiveExprInterface
**/
static void install_interpreter_conversions(ObjectConverter * target);
static void install(gc::IAlloc * mm, gp<GlobalEnv> env);
};
}

View file

@ -75,14 +75,30 @@ namespace xo {
* - expr_ input, caller saves
* - env_ input, caller saves
* - cont_ input, caller saves
* - stack_ input, caller saves
* - value_ output
* - error_ output
*
**/
void execute_one();
/* design note:
* - eval_xxx_op() methods are primary VSM transitions,
* in the sense that they begin a sequence of transitions to interpret a
* particular kind of expression
* - do_xxx_op() methods represent secondary VSM transitions,
* that continue an instruction sequence that was initiated by a preceding
* eval_xxx_op() method
*/
/** interpret literal constant expression **/
void eval_constant_op();
/** interpreter literal primitive expression
* (these appear implicitly as result of builtin operators like {+, ==, ..})
**/
void eval_primitive_op();
/** execute define expression (finished in do_complete_assign_op()) **/
void eval_define_op();
/** execute assign expression (finishes in do_complete_assign_op()) **/
@ -98,11 +114,22 @@ namespace xo {
/** continue after establish value of test expression **/
void do_complete_ifexpr_op();
/** interprete sequence **/
/** interpret sequence **/
void eval_sequence_op();
/** continue after establishing value for a sequence element **/
void do_complete_sequence_op();
/** interpret apply-expression (i.e. function call) **/
void eval_apply_op();
/** continue assembling args for a function call;
* transition to (interpretation of) called function once all arguments
* are evaluated.
**/
void do_complete_evalargs_op();
/** execute function application, given actuals in top stack frame **/
void apply_op();
/** goto error state with message @p err **/
void report_error(const std::string & err);

View file

@ -41,6 +41,17 @@ namespace xo {
**/
complete_sequence,
/** execute remainder of argument sequence evaluation;
* subsidiary to marshalling a function call
**/
complete_evalargs,
/** Call a function. Arguments have been evaluated
* and are in top stack frame, in order,
* starting with target function itself
**/
apply,
/** choose branch of if-expression + continue
*
* stack: frame with

View file

@ -23,15 +23,13 @@ namespace xo {
public:
VsmStackFrame(gc::IAlloc * mm, gp<VsmStackFrame> p, std::size_t n, const VsmInstr * cont);
#ifdef NOT_YET
/** create frame using allocator @p mm,
* with parent @p p and exactly @p n_slot object pointers.
**/
static gp<VsmStackFrame> make(gc::IAlloc * mm,
gp<VsmStackFrame> p,
const VsmInstr * cont,
std::size_t n_slot);
#endif
std::size_t n_slot,
const VsmInstr * cont);
/** create new stack frame using allocator @p mm,
* with parent frame @p p; new frame contains values @p s0
@ -56,6 +54,7 @@ namespace xo {
gp<VsmStackFrame> parent() const { return parent_; }
std::size_t size() const { return slot_v_.size(); }
const obj::CVector<gp<Object>> & argv() const { return slot_v_; }
const VsmInstr * continuation() const { return cont_; }
gp<Object> operator[](std::size_t i) const { return slot_v_[i]; }