|
@@ -10,7 +10,7 @@
|
10
|
10
|
#include "dsl/dsl.h"
|
11
|
11
|
|
12
|
12
|
/** The version of the project, as made available through `debug.version`. */
|
13
|
|
-#define VERSION "0.2a0"
|
|
13
|
+#define VERSION "0.2a1"
|
14
|
14
|
/** The hexadecimal version of the project, formatted 0xAAIIRPP where:
|
15
|
15
|
*
|
16
|
16
|
* - AA is the two-digit major version
|
|
@@ -20,7 +20,7 @@
|
20
|
20
|
*
|
21
|
21
|
* This value is guaranteed to always increase by revision.
|
22
|
22
|
*/
|
23
|
|
-#define HEXVER 0x0002A00
|
|
23
|
+#define HEXVER 0x0002A01
|
24
|
24
|
|
25
|
25
|
#ifndef SOL_ICACHE_MIN
|
26
|
26
|
/** The smallest integer to cache. */
|
|
@@ -380,111 +380,327 @@ typedef struct sol_tag_object_t {
|
380
|
380
|
typedef enum {SF_NORMAL, SF_BREAKING, SF_CONTINUING} sol_state_flag_t;
|
381
|
381
|
|
382
|
382
|
typedef struct sol_tag_state_t {
|
383
|
|
- sol_object_t *scopes; // A list of scope maps, innermost out, ending at the global scope
|
384
|
|
- sol_object_t *ret; // Return value of this function, for early return
|
385
|
|
- sol_object_t *traceback; // The last stack of statement (nodes) in the last error, or NULL
|
386
|
|
- sol_state_flag_t sflag; // Used to implement break/continue
|
387
|
|
- sol_object_t *error; // Some arbitrary error descriptor, None if no error
|
388
|
|
- sol_object_t *stdout; // Standard output stream object (for print())
|
389
|
|
- sol_object_t *stdin; // Standard input stream object
|
390
|
|
- sol_object_t *stderr; // Standard error stream object
|
391
|
|
- sol_object_t *None;
|
392
|
|
- sol_object_t *OutOfMemory;
|
393
|
|
- sol_object_t *StopIteration;
|
394
|
|
- sol_ops_t NullOps;
|
395
|
|
- sol_ops_t SingletOps;
|
396
|
|
- sol_ops_t IntOps;
|
397
|
|
- sol_ops_t FloatOps;
|
398
|
|
- sol_ops_t StringOps;
|
399
|
|
- sol_ops_t ListOps;
|
400
|
|
- sol_ops_t MapOps;
|
401
|
|
- sol_ops_t MCellOps;
|
402
|
|
- sol_ops_t FuncOps;
|
403
|
|
- sol_ops_t CFuncOps;
|
404
|
|
- sol_ops_t ASTNodeOps;
|
405
|
|
- sol_ops_t BufferOps;
|
406
|
|
- sol_ops_t DyLibOps;
|
407
|
|
- sol_ops_t DySymOps;
|
408
|
|
- sol_ops_t StreamOps;
|
409
|
|
- sol_object_t *modules;
|
410
|
|
- sol_object_t *methods;
|
411
|
|
- dsl_object_funcs obfuncs;
|
412
|
|
- const char *calling_type;
|
413
|
|
- const char *calling_meth;
|
|
383
|
+ sol_object_t *scopes; ///< A list of scope maps, innermost out, ending at the global scope
|
|
384
|
+ sol_object_t *ret; ///< Return value of this function, for early return
|
|
385
|
+ sol_object_t *traceback; ///< The last stack of statement (nodes) in the last error, or NULL
|
|
386
|
+ sol_state_flag_t sflag; ///< Used to implement break/continue
|
|
387
|
+ sol_object_t *error; ///< Some arbitrary error descriptor, `None` if no error
|
|
388
|
+ sol_object_t *stdout; ///< Standard output stream object (for print(), type `SOL_STREAM`)
|
|
389
|
+ sol_object_t *stdin; ///< Standard input stream object (type `SOL_STREAM`)
|
|
390
|
+ sol_object_t *stderr; ///< Standard error stream object (type `SOL_STREAM`)
|
|
391
|
+ sol_object_t *None; ///< The all-important `None` object
|
|
392
|
+ sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object
|
|
393
|
+ sol_object_t *StopIteration; ///< The somewhat-important `StopIteration` object
|
|
394
|
+ sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type.
|
|
395
|
+ sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, `StopIteration`, etc.)
|
|
396
|
+ sol_ops_t IntOps; ///< Operations on integers
|
|
397
|
+ sol_ops_t FloatOps; ///< Operations on floats
|
|
398
|
+ sol_ops_t StringOps; ///< Operations on strings
|
|
399
|
+ sol_ops_t ListOps; ///< Operations on lists
|
|
400
|
+ sol_ops_t MapOps; ///< Operations on maps
|
|
401
|
+ sol_ops_t MCellOps; ///< Operations on map cells (rarely used)
|
|
402
|
+ sol_ops_t FuncOps; ///< Operations on functions
|
|
403
|
+ sol_ops_t CFuncOps; ///< Operations on C functions
|
|
404
|
+ sol_ops_t ASTNodeOps; ///< Operations on AST nodes
|
|
405
|
+ sol_ops_t BufferOps; ///< Operations on buffers
|
|
406
|
+ sol_ops_t DyLibOps; ///< Operations on dynamic library objects
|
|
407
|
+ sol_ops_t DySymOps; ///< Operations on dynamic symbol objects
|
|
408
|
+ sol_ops_t StreamOps; ///< Operations on streams
|
|
409
|
+ sol_object_t *modules; ///< A map of modules, string name to contents, resolved at "super-global" scope (and thus overrideable)
|
|
410
|
+ sol_object_t *methods; ///< A map of string names to methods (like "list" -> {insert=<CFunction>, remove=<CFunction>, ...}) free for private use by extension developers
|
|
411
|
+ dsl_object_funcs obfuncs; ///< The set of object functions that allows DSL to integrate with Sol's reference counting
|
|
412
|
+ const char *calling_type; ///< Set (during `CALL_METHOD`) to determine the type (ops structure) being invoked for this method (mostly for sol_f_not_impl)
|
|
413
|
+ const char *calling_meth; ///< Set (during `CALL_METHOD`) to determine the method name being invoked (mostly for sol_f_not_impl)
|
414
|
414
|
#ifdef SOL_ICACHE
|
415
|
|
- sol_object_t *icache[SOL_ICACHE_MAX - SOL_ICACHE_MIN + 1];
|
416
|
|
- char icache_bypass;
|
|
415
|
+ sol_object_t *icache[SOL_ICACHE_MAX - SOL_ICACHE_MIN + 1]; ///< The integer cache (holds integers from `SOL_ICACHE_MIN` to `SOL_ICACHE_MAX` indexed by `[i - SOL_ICACHE_MIN]`)
|
|
416
|
+ char icache_bypass; ///< Set to true to bypass caching--needed to avoid infinite recursion when initially populating the cache
|
417
|
417
|
#endif
|
418
|
|
- sol_object_t *lastvalue;
|
419
|
|
- sol_object_t *loopvalue;
|
|
418
|
+ sol_object_t *lastvalue; ///< Holds the value of the last expression evaluated, returned by an `if` expression
|
|
419
|
+ sol_object_t *loopvalue; ///< Holds an initially-empty list appended to by `continue <expr>` or set to another object by `break <expr>`
|
420
|
420
|
} sol_state_t;
|
421
|
421
|
|
422
|
422
|
// state.c
|
423
|
423
|
|
|
424
|
+/** Initializes the state.
|
|
425
|
+ *
|
|
426
|
+ * This should be called once (and only once!) for every state; it does the important
|
|
427
|
+ * work of ensuring that the state is ready to execute code, including:
|
|
428
|
+ *
|
|
429
|
+ * - Creating the initial singlet values `None`, `OutOfMemory`, and `StopIteration`,
|
|
430
|
+ * - Creating and populating the operations on all internally-defined object types.
|
|
431
|
+ * - Initializing all built-in modules and methods.
|
|
432
|
+ * - Running any "init.sol" files.
|
|
433
|
+ * - Recognizing early-init errors and aborting.
|
|
434
|
+ *
|
|
435
|
+ * It is the singular, monolithic place where most pre-execution occurs, and language
|
|
436
|
+ * developers may thus use it at their discretion. Extension developers should provide
|
|
437
|
+ * their own documented initializers, and embedders should do their own initialization
|
|
438
|
+ * immediately after calling this function.
|
|
439
|
+ */
|
424
|
440
|
int sol_state_init(sol_state_t *);
|
|
441
|
+/** Cleans up the state.
|
|
442
|
+ *
|
|
443
|
+ * In theory, after calling this, the state should be ready to be released (e.g., freed
|
|
444
|
+ * if it was allocated on the heap). Importantly, it should NOT be used for any code
|
|
445
|
+ * execution after this call (it WILL segfault).
|
|
446
|
+ */
|
425
|
447
|
void sol_state_cleanup(sol_state_t *);
|
426
|
448
|
|
|
449
|
+/** Resolve a name.
|
|
450
|
+ *
|
|
451
|
+ * Technically, a "name" can be anything (any key in a map, more precisely), but the
|
|
452
|
+ * runtime (and most sane code) generally depends on names being strings. It is, however,
|
|
453
|
+ * emphatically possible to populate the scopes with non-string names--for potential use
|
|
454
|
+ * cases, see `programs/monty.sol`
|
|
455
|
+ */
|
427
|
456
|
sol_object_t *sol_state_resolve(sol_state_t *, sol_object_t *);
|
|
457
|
+/** Resolve a string name, given as a C string.
|
|
458
|
+ *
|
|
459
|
+ * This handles the popular case where a C program would like to resolve the value of a
|
|
460
|
+ * variable by (string) name. In particular, it handles the memory of doing so properly.
|
|
461
|
+ */
|
428
|
462
|
sol_object_t *sol_state_resolve_name(sol_state_t *, const char *);
|
|
463
|
+/** Assign to a global name.
|
|
464
|
+ *
|
|
465
|
+ * This is rarely used, except in `sol_state_init`. It sets the value of the given name
|
|
466
|
+ * (as an object) in the global (outermost) scope. Code execution generally uses the
|
|
467
|
+ * local scope instead.
|
|
468
|
+ */
|
429
|
469
|
void sol_state_assign(sol_state_t *, sol_object_t *, sol_object_t *);
|
|
470
|
+/** Assign to a global string name, given as a C string.
|
|
471
|
+ *
|
|
472
|
+ * This is a convenience for `sol_state_assign`, which handles the creation and destruction
|
|
473
|
+ * of the Sol string.
|
|
474
|
+ */
|
430
|
475
|
void sol_state_assign_name(sol_state_t *, const char *, sol_object_t *);
|
|
476
|
+/** Assign to a local name.
|
|
477
|
+ *
|
|
478
|
+ * Sets the name to the value in the local (innermost) scope. It has the functional equivalent
|
|
479
|
+ * of the Sol code `<name> = <value>` in whatever context the state is in.
|
|
480
|
+ */
|
431
|
481
|
void sol_state_assign_l(sol_state_t *, sol_object_t *, sol_object_t *);
|
|
482
|
+/** Assign to a local string name, given as a C string.
|
|
483
|
+ *
|
|
484
|
+ * Another convenience for `sol_state_assign_l`.
|
|
485
|
+ */
|
432
|
486
|
void sol_state_assign_l_name(sol_state_t *, const char *, sol_object_t *);
|
433
|
487
|
|
|
488
|
+/** Push a scope.
|
|
489
|
+ *
|
|
490
|
+ * This adds a new (more-local) scope to the scope stack (`state->scopes`). This permits values
|
|
491
|
+ * in such a scope to be manipulated independently of those in enclosing scopes, and their references
|
|
492
|
+ * are discarded during the next `sol_state_pop_scope`. (The values may, of course, be present via
|
|
493
|
+ * other references.)
|
|
494
|
+ *
|
|
495
|
+ * Scope stack manipulation MUST be balanced; egregious errors will occur otherwise.
|
|
496
|
+ *
|
|
497
|
+ * Scope stack manipulation is generally only necessary where another environment is expected for the
|
|
498
|
+ * code running in that context; e.g., the body of a function, or an AST node from an imported file. In
|
|
499
|
+ * particular, most control structures do NOT introduce scopes, due to the deleterious effects of having
|
|
500
|
+ * no direct influence on enclosing scopes.
|
|
501
|
+ */
|
434
|
502
|
void sol_state_push_scope(sol_state_t *, sol_object_t *);
|
|
503
|
+/** Pops a scope.
|
|
504
|
+ *
|
|
505
|
+ * Removes and discards the local scope. All names and associated value references are lost.
|
|
506
|
+ *
|
|
507
|
+ * This MUST be balanced with `sol_state_push_scope`.
|
|
508
|
+ */
|
435
|
509
|
sol_object_t *sol_state_pop_scope(sol_state_t *);
|
436
|
510
|
|
|
511
|
+/** Returns the current error.
|
|
512
|
+ *
|
|
513
|
+ * This object is `None` if there is no error. See `sol_has_error`.
|
|
514
|
+ */
|
437
|
515
|
sol_object_t *sol_get_error(sol_state_t *);
|
|
516
|
+/** Set the current error.
|
|
517
|
+ *
|
|
518
|
+ * Sets the current error object. Clears the error if the object is `None`.
|
|
519
|
+ */
|
438
|
520
|
sol_object_t *sol_set_error(sol_state_t *, sol_object_t *);
|
|
521
|
+/** Set the current error to a string, given a C string.
|
|
522
|
+ *
|
|
523
|
+ * Conveniently sets the error to a string object created from the given C string.
|
|
524
|
+ */
|
439
|
525
|
sol_object_t *sol_set_error_string(sol_state_t *, const char *);
|
|
526
|
+/** Clear the current error.
|
|
527
|
+ *
|
|
528
|
+ * Equivalent to `sol_set_error(state, state->None)`.
|
|
529
|
+ */
|
440
|
530
|
void sol_clear_error(sol_state_t *);
|
441
|
531
|
|
|
532
|
+/** Prepares a traceback.
|
|
533
|
+ *
|
|
534
|
+ * Initializes the traceback stack to an empty list in preparation of `sol_add_traceback`.
|
|
535
|
+ * Typically used by the runtime while recovering from an error; the value is ultimately
|
|
536
|
+ * returned as the third element of the return list from `try`.
|
|
537
|
+ */
|
442
|
538
|
void sol_init_traceback(sol_state_t *);
|
|
539
|
+/** Adds an object to a traceback.
|
|
540
|
+ *
|
|
541
|
+ * This object is usually an ASTNode; typically, it is a statement which was being executed
|
|
542
|
+ * when the relevant error occurred. This object is made the first item of the traceback pair
|
|
543
|
+ * (the second element is the current local scope).
|
|
544
|
+ */
|
443
|
545
|
void sol_add_traceback(sol_state_t *, sol_object_t *);
|
|
546
|
+/** Gets the traceback.
|
|
547
|
+ *
|
|
548
|
+ * This will be a list of traceback pairs; each such pair will be [<value given to `sol_add_traceback`>,
|
|
549
|
+ * <local scope>].
|
|
550
|
+ */
|
444
|
551
|
sol_object_t *sol_traceback(sol_state_t *);
|
445
|
552
|
|
|
553
|
+/** Registers a module.
|
|
554
|
+ *
|
|
555
|
+ * Creates a module entry by name, referring to its value. Modules resolve after globals, and
|
|
556
|
+ * therefore form a sort of untouchable "super-global" scope. Most built-in modules reside in
|
|
557
|
+ * this namespace.
|
|
558
|
+ */
|
446
|
559
|
void sol_register_module(sol_state_t *, sol_object_t *, sol_object_t *);
|
|
560
|
+/** Registers a module by string name, given a C string.
|
|
561
|
+ *
|
|
562
|
+ * A convenience for `sol_register_module`.
|
|
563
|
+ */
|
447
|
564
|
void sol_register_module_name(sol_state_t *, char *, sol_object_t *);
|
|
565
|
+/** Gets a module.
|
|
566
|
+ *
|
|
567
|
+ * Retrieves a module by its given name. Its value will be as it was registered.
|
|
568
|
+ */
|
448
|
569
|
sol_object_t *sol_get_module(sol_state_t *, sol_object_t *);
|
|
570
|
+/** Gets a module by string name, given a C string.
|
|
571
|
+ *
|
|
572
|
+ * A convenience for `sol_get_module`.
|
|
573
|
+ */
|
449
|
574
|
sol_object_t *sol_get_module_name(sol_state_t *, char *);
|
|
575
|
+/** Registers methods.
|
|
576
|
+ *
|
|
577
|
+ * Creates a methods entry by name, referring to its value. Methods are never resolved directly
|
|
578
|
+ * by (non-debug) code, but are used liberally throughout the C interface for implementing named
|
|
579
|
+ * methods on objects (such as lists, buffers, etc.) that wouldn't normally resolve names--thus
|
|
580
|
+ * the name. Thus, the mapping forms a sort of private namespace that may freely be used by
|
|
581
|
+ * developers as they see fit.
|
|
582
|
+ */
|
450
|
583
|
void sol_register_methods(sol_state_t *, sol_object_t *, sol_object_t *);
|
|
584
|
+/** Registers a method by string name, given a C string.
|
|
585
|
+ *
|
|
586
|
+ * A convenience for `sol_register_methods`.
|
|
587
|
+ */
|
451
|
588
|
void sol_register_methods_name(sol_state_t *, char *, sol_object_t *);
|
|
589
|
+/** Gets methods.
|
|
590
|
+ *
|
|
591
|
+ * Retrieves the methods by its name, returning the value that was registered.
|
|
592
|
+ */
|
452
|
593
|
sol_object_t *sol_get_methods(sol_state_t *, sol_object_t *);
|
|
594
|
+/** Gets methods by string name, given a C string.
|
|
595
|
+ *
|
|
596
|
+ * A convenience for `sol_get_methods`.
|
|
597
|
+ */
|
453
|
598
|
sol_object_t *sol_get_methods_name(sol_state_t *, char *);
|
454
|
599
|
|
|
600
|
+/** Index operation override for the `io` module.
|
|
601
|
+ *
|
|
602
|
+ * This hook virtually provides `stdin`, `stdout`, and `stderr` by returning the relevant
|
|
603
|
+ * values on the states.
|
|
604
|
+ */
|
455
|
605
|
sol_object_t *sol_f_io_index(sol_state_t *, sol_object_t *);
|
|
606
|
+/** Setindex operation override for the `io` module.
|
|
607
|
+ *
|
|
608
|
+ * This hook intercepts and specially handles attempts to set `stdin`, `stdout`, and `stderr`
|
|
609
|
+ * by setting the relevant values on the state.
|
|
610
|
+ */
|
456
|
611
|
sol_object_t *sol_f_io_setindex(sol_state_t *, sol_object_t *);
|
|
612
|
+/** Retrieves the stdin stream.
|
|
613
|
+ *
|
|
614
|
+ * Returns the stream object used to read program input.
|
|
615
|
+ */
|
457
|
616
|
sol_object_t *sol_get_stdin(sol_state_t *);
|
|
617
|
+/** Retrieves the stdout stream.
|
|
618
|
+ *
|
|
619
|
+ * Returns the stream object used to write program output.
|
|
620
|
+ */
|
458
|
621
|
sol_object_t *sol_get_stdout(sol_state_t *);
|
|
622
|
+/** Retrieves the stderr stream.
|
|
623
|
+ *
|
|
624
|
+ * Returns the stream object used to write program errors or out-of-band data.
|
|
625
|
+ */
|
459
|
626
|
sol_object_t *sol_get_stderr(sol_state_t *);
|
460
|
627
|
|
|
628
|
+/** Initializes an ops structure.
|
|
629
|
+ *
|
|
630
|
+ * This sets all the fields of a `sol_ops_t` to their sensible defaults. Such an initialized
|
|
631
|
+ * structure is available on the state as `state->NullOps`.
|
|
632
|
+ */
|
461
|
633
|
void sol_ops_init(sol_ops_t *);
|
462
|
634
|
|
463
|
635
|
// builtins.c
|
464
|
636
|
|
|
637
|
+/** Not implemented handler.
|
|
638
|
+ *
|
|
639
|
+ * This raises the "Undefined method" error.
|
|
640
|
+ */
|
465
|
641
|
sol_object_t *sol_f_not_impl(sol_state_t *, sol_object_t *);
|
|
642
|
+/** !!! handler.
|
|
643
|
+ *
|
|
644
|
+ * Swaps objects by value.
|
|
645
|
+ */
|
466
|
646
|
sol_object_t *sol_f_tbang(sol_state_t *, sol_object_t *);
|
|
647
|
+/** No operation handler.
|
|
648
|
+ *
|
|
649
|
+ * Does nothing.
|
|
650
|
+ */
|
467
|
651
|
sol_object_t *sol_f_no_op(sol_state_t *, sol_object_t *);
|
|
652
|
+/** Default comparison handler.
|
|
653
|
+ *
|
|
654
|
+ * Returns 0 (equal) if the references refer to exactly the same object, or
|
|
655
|
+ * 1 (greater) otherwise.
|
|
656
|
+ *
|
|
657
|
+ * Note that this is not a partial order.
|
|
658
|
+ */
|
468
|
659
|
sol_object_t *sol_f_default_cmp(sol_state_t *, sol_object_t *);
|
|
660
|
+/** Default tostring handler.
|
|
661
|
+ *
|
|
662
|
+ * Returns a string formatted as "<<typename> object at <address>>".
|
|
663
|
+ */
|
469
|
664
|
sol_object_t *sol_f_default_tostring(sol_state_t *, sol_object_t *);
|
|
665
|
+/** Default torepr handler.
|
|
666
|
+ *
|
|
667
|
+ * Returns tostring(object).
|
|
668
|
+ */
|
470
|
669
|
sol_object_t *sol_f_default_repr(sol_state_t *, sol_object_t *);
|
471
|
670
|
|
|
671
|
+/// Built-in function toint
|
472
|
672
|
sol_object_t *sol_f_toint(sol_state_t *, sol_object_t *);
|
|
673
|
+/// Built-in function tofloat
|
473
|
674
|
sol_object_t *sol_f_tofloat(sol_state_t *, sol_object_t *);
|
|
675
|
+/// Built-in function tostring
|
474
|
676
|
sol_object_t *sol_f_tostring(sol_state_t *, sol_object_t *);
|
|
677
|
+/// Built-in function try
|
475
|
678
|
sol_object_t *sol_f_try(sol_state_t *, sol_object_t *);
|
|
679
|
+/// Built-in function error
|
476
|
680
|
sol_object_t *sol_f_error(sol_state_t *, sol_object_t *);
|
|
681
|
+/// Built-in function type
|
477
|
682
|
sol_object_t *sol_f_type(sol_state_t *, sol_object_t *);
|
|
683
|
+/// Built-in function prepr
|
478
|
684
|
sol_object_t *sol_f_prepr(sol_state_t *, sol_object_t *);
|
|
685
|
+/// Built-in function print
|
479
|
686
|
sol_object_t *sol_f_print(sol_state_t *, sol_object_t *);
|
|
687
|
+/// Built-in function rawget
|
480
|
688
|
sol_object_t *sol_f_rawget(sol_state_t *, sol_object_t *);
|
|
689
|
+/// Built-in function rawset
|
481
|
690
|
sol_object_t *sol_f_rawset(sol_state_t *, sol_object_t *);
|
|
691
|
+/// Built-in function range
|
482
|
692
|
sol_object_t *sol_f_range(sol_state_t *, sol_object_t *);
|
|
693
|
+/// Built-in function exec
|
483
|
694
|
sol_object_t *sol_f_exec(sol_state_t *, sol_object_t *);
|
|
695
|
+/// Built-in function eval
|
484
|
696
|
sol_object_t *sol_f_eval(sol_state_t *, sol_object_t *);
|
|
697
|
+/// Built-in function execfile
|
485
|
698
|
sol_object_t *sol_f_execfile(sol_state_t *, sol_object_t *);
|
|
699
|
+/// Built-in function parse
|
486
|
700
|
sol_object_t *sol_f_parse(sol_state_t *, sol_object_t *);
|
|
701
|
+/// Built-in function ord
|
487
|
702
|
sol_object_t *sol_f_ord(sol_state_t *, sol_object_t *);
|
|
703
|
+/// Built-in function chr
|
488
|
704
|
sol_object_t *sol_f_chr(sol_state_t *, sol_object_t *);
|
489
|
705
|
|
490
|
706
|
sol_object_t *sol_f_debug_getref(sol_state_t *, sol_object_t *);
|