[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [epsilon-devel] Questions

From: Luca Saiu
Subject: Re: [epsilon-devel] Questions
Date: Thu, 02 Jan 2014 03:01:18 +0100
User-agent: Gnus (Ma Gnus v0.8), GNU Emacs, x86_64-unknown-linux-gnu

Hello amz3.

On 2013-12-30 at 04:39, address@hidden wrote:

> I need answer right now because I would like to have the answers
> tomorrow when I will wake up (probably very late), anyway feel free to
> answer when you want.

I'm sorry, it took me a little longer.

> I don't see buffer:set! in epsilon0-in-scheme.scm but it's defined in
> core.e

It's actually a primitive, but core.e defines its procedure wrapper.

buffer:set! is a "store" operation, letting you change the content of a
buffer at a given offset.  It takes three parameters:
- buffer;
- offset (in words);
- new content.
It returns zero results.

> Through which procedure is it possible to modify the global state in
> epsilon0?

As I told you the other day, the boundary between epsilon0 and epsilon1
at the library level is purely conventional.  However what I usually
mean when I speak of global state is:
- procedure definitions;
- global (non-procedure) definitions.
If you are interested in this (and it's quite reasonable that you are,
if you want to reimplement epsilon0) have a look at the section named
"State: global dynamic state, with reflection" in core.e.  You will see
that it's a thin wrapper over symbols because, as I wrote the last time,
a symbol is a buffer containing the global bindings for each name.
You may also want to check the tutorial, starting at "Let’s have a look
at the symbol foo as a data structure:".

The procedures doing what you ask are state:global-set! and
state:procedure-set!, defined in core.e.  They are easy to understand:

--8<---------------cut here---------------start------------->8---
(e1:define (state:global-set! name value)
  (e0:let () (buffer:set! name (e0:value 1) (e0:value 1)) ;; bound
    (buffer:set! name (e0:value 2) value))) ;; value

(e1:define (state:procedure-set! name formals body)
  (e0:let () (buffer:set! name (e0:value 3) formals)
    (buffer:set! name (e0:value 4) body)))
--8<---------------cut here---------------end--------------->8---

There's a very slight complication in state:global-set!: in order to
record the fact that a symbol names a global variable with a certain
value, just storing the value (field #2) isn't enough: we also need to
store the fact that the value is there, in field #1.  The reason is that
we can't reserve any value to represent a special "undefined" object in
#2; any value, for example 0 or -1, is potentially valid as the value of
a global variable.

procedure-set! doesn't have this problem: since the unboxed value 0 is
not a valid representation of any epsilon0 expression, having 0 in field
#4, the procedure body, suffices to mark the procedure binding as not
present.  I decided to do this trick on the body, because it wouldn't
work on the formal parameter list: 0 is a valid list representation; it
represents the empty list, and of course procedures are allowed to have
zero parameters.

state:procedure-set!, by itself, is not hard to use: the annoying part
is building an epsilon0 expression programmatically.  You could
procedural constructors for this, should you ever need it for some
strange reason.  But if you have epsilon1 available, there should always
be easier ways, such as using e1:macroexpand.  Let's try:

(e1:toplevel (e1:macroexpand '(e1:if x 10 20)))
0x1198b80[7 83783 0x115d5c0[0 83781 0x1105860[...]] 0x115d600[0 0] 0x113cb00[1 
83780 20] 0x1072220[1 83782 10]]

Not so easy to read, so let's use my Guile debugging procedure to print
out how (e1:if x 10 20) is rewritten in epsilon0, in handy concrete
syntax; only handles will be different, because the macroexpansion will
be re-executed:

(meta:macroexpand '(e1:if x 10 20))
[if x₈₃₈₃₁ ∈ {0} then 20₈₃₈₃₀ else 10₈₃₈₃₂]₈₃₈₃₃

Now it's quite clear: (e1:if x 10 20), using an epsilon1 conditional, is
rewritten by macroexpand into the simpler epsilon0 conditional called
e0:if-in : if x belongs to the set containing only zero, then the result
is the literal constant 20; otherwise the result is the literal constant
10.  Of course the false value is represented as zero, that's why the
conditional works like that: any non-zero value counts as true.

So, back again.  Go to the "Expressions" section in core.e, and look at
the definition of e0:expression.  This lets you understand pretty well
how expressions are represented: they are a sum type, as you saw in the
tutorial.  And you can guess the tag from the order of cases.  Let's read
0x1198b80[7 83783 0x115d5c0[0 83781 0x1105860[...]] 0x115d600[0 0] 0x113cb00[1 
83780 20] 0x1072220[1 83782 10]]

7 is the if-in tag (if-in is the eight case: we count from zero), so the
outermost expression is an if; it happens to have 83783 as its handle.
Then comes the discriminand expression: it's written as "x", which is to
say a variable (tag 0), handle 83781; 0x1105860 is the symbol x.  After
the conditional, we have 0x115d600, the list of values to be compared
with the discriminand: in this case it's a one-element list, and the
element is 0.  The list is represented as a pair <0, end-of-list>; and
the end of list is represented as 0 as well, so 0x115d600 contains two 0
values.  Then comes 0x113cb00, the "then" branch: we know it's written
as "20": in fact 0x113cb00 is a literal (tag 1), it happens to have
handle 83780, and indeed it contains the value 20 (notice that there's
no type information at all: 20 might also be a character, or an
enumerate, or anything else); finally we have 0x1072220, the else
branch: again a literal (tag 1), handle 83782, content 10.

I went a little off-topic, but I think this might answer some of your
curiosities about the global state and about what expressions "are".

If you want to alter the epsilon0 global state with procedures, there
are also state:global-unset! state:procedure-unset!; they do exactly
what you think they do.

Luca Saiu
Home page:   http://ageinghacker.net
GNU epsilon: http://www.gnu.org/software/epsilon
Marionnet:   http://marionnet.org

reply via email to

[Prev in Thread] Current Thread [Next in Thread]