mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-29 10:27:58 +03:00
A few things.
The S_REF instruction creates a _copy_ of the referenced string. Proof:
FUNC foo
// string local_string = "foo"
SH_LOCALREF local_string
S_PUSH "foo"
S_ASSIGN
S_POP
// prepare argument for bar()
PUSHLOCALPAGE
PUSH local_string
S_REF
// stealthily alter local_string
SH_LOCALREF local_string
S_PUSH "bar"
S_ASSIGN
S_POP
// bar(local_string)
CALLFUNC bar // local_string is still "foo" in the body of bar()!
Thus, it is not CALLFUNC's responsibility to copy by-value string
arguments. CALLFUNC need only copy the index from the stack into the
local page.
Objects pushed to the stack with SH_LOCALREF, SH_GLOBALREF and REF do
not gain a reference. They are already referenced by the page they
belong to.
I believe the implementation of S_REF is still not quite right. What
I've noticed is that System40.exe is able to distinguish between strings
pushed with S_REF/S_PUSH and strings pushed with
SH_LOCALREF/SH_GLOBALREF/REF. It seems the former are r-values and the
latter are l-values (i.e. the latter can be assigned to, but not the
former), and the VM will throw an error if you try to assign to an
r-value.
The underlying implementation is not clear to me. Both types appear to
be indices into the heap, which suggests that the distinguishing factor
must be stored either in the object itself, or as part of the pointer to
an object. Perhaps its as simple as a flag marking an object as an
r-value?
66 lines
2.0 KiB
C
66 lines
2.0 KiB
C
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef SYSTEM4_H
|
|
#define SYSTEM4_H
|
|
|
|
#include <stddef.h>
|
|
|
|
// TODO: should put in a separate header and guard with feature checks
|
|
#define const_pure __attribute__((const))
|
|
#define mem_alloc __attribute__((malloc))
|
|
#define noreturn _Noreturn
|
|
|
|
#define ERROR(fmt, ...) \
|
|
sys_error("*ERROR*(%s:%s:%d): " fmt "\n", __FILE__, __func__, __LINE__, ##__VA_ARGS__)
|
|
|
|
#define WARNING(fmt, ...) \
|
|
sys_message("*WARNING*(%s:%s:%d): " fmt "\n", __FILE__, __func__, __LINE__, ##__VA_ARGS__)
|
|
|
|
#define NOTICE(fmt, ...) \
|
|
sys_message(fmt "\n", ##__VA_ARGS__)
|
|
|
|
noreturn void sys_error(char *fmt, ...);
|
|
void sys_warning(char *fmt, ...);
|
|
void sys_message(char *fmt, ...);
|
|
|
|
noreturn void sys_exit(int code);
|
|
|
|
#define xmalloc(size) _xmalloc(size, __func__)
|
|
mem_alloc void *_xmalloc(size_t size, const char *func);
|
|
|
|
#define xrealloc(ptr, size) _xrealloc(ptr, size, __func__)
|
|
mem_alloc void *_xrealloc(void *ptr, size_t size, const char *func);
|
|
|
|
#define xstrdup(str) _xstrdup(str, __func__)
|
|
mem_alloc char *_xstrdup(const char *in, const char *func);
|
|
|
|
#define max(a, b) \
|
|
({ \
|
|
__typeof__ (a) _a = (a); \
|
|
__typeof__ (b) _b = (b); \
|
|
_a > _b ? _a : _b; \
|
|
})
|
|
|
|
#define min(a, b) \
|
|
({ \
|
|
__typeof__ (a) _a = (a); \
|
|
__typeof__ (b) _b = (b); \
|
|
_a < _b ? _a : _b; \
|
|
})
|
|
|
|
#endif /* SYSTEM4_H */
|