actonlang / acton Goto Github PK
View Code? Open in Web Editor NEWThe Acton Programming Language
Home Page: https://www.acton-lang.org/
License: BSD 3-Clause "New" or "Revised" License
The Acton Programming Language
Home Page: https://www.acton-lang.org/
License: BSD 3-Clause "New" or "Revised" License
All the compilation output currently goes in the same directory, which is in the Acton system directory. After #43 we at least split up so that system builtin and shipped modules are in libActon.a
whereas project related go in libActonProject.a
, still, both are placed in the lib
directory in the system directory.
We should split this up to make it possible to install Acton on a system outside of a users home directory, yet let the user compile an Acton project in their home directory.
Acton projects typically live in the users home directory and when compiled should produce output in the Acton project directory. This also makes it possible to have multiple Acton projects with potentially overlapping module names but without creating conflicts.
Today, an .acton
file marks a directory as a module? Is this correct? It's a little weird to me - I think they're too far in, I think I would rather mark something an Acton project and then presume the remainder of the directory structure based on that, something along the lines of (where Acton.toml marks this as an Acton project, similar to Rust's Cargo which has a Cargo.toml):
my-acton-project/
├── Acton.toml
├── out
│ ├── bin
│ │ └── main
│ ├── lib
│ └── modules
└── src
├── foo
│ └── bar.act
└── main.act
in main.act
we can then do
import foo.bar
and access the things. I'm not quite sure how to structure the compiled output, but I think it should go in my-acton-project at least. I put a out
directory that more or less replicates the things we currently write to the acton system directory but in the project directory instead. Under it we can write a project local modules and lib. Did a POC patch (there is some debug output printed first, ignore... or not). It finds the project path based on the presence of a Acton.toml
file there, then assumes src
exists in there etc:
kll@ThinkYoga:~/kod/my-acton-project$ actonc --verbose src/foo/kaka/banan.act
projPath: /home/kll/kod/my-acton-project
subdirs: src foo kaka
dirInSrc: foo kaka
fileBody: banan
srcPath: /home/kll/kod/my-acton-project/src/foo/kaka
## sysPath : /home/kll/terastream/acton
## sysMod : /home/kll/terastream/acton/modules
## sysLib : /home/kll/terastream/acton/lib
## sysRoot : /home/kll/terastream/acton/modules
## projPath : /home/kll/kod/my-acton-project
## projMod : /home/kll/kod/my-acton-project/out/modules
## projLib : /home/kll/kod/my-acton-project/out/lib
## srcRoot : /home/kll/kod/my-acton-project/src
## modPrefix: foo
## topMod : foo.kaka.banan
Compiling /home/kll/kod/my-acton-project/src/kaka/banan.act... Done.
kll@ThinkYoga:~/kod/my-acton-project$
In this case the Acton system is "installed" in /home/kll/terastream/acton
(which we "find" based on the location of actonc, which I've included in my PATH
). This should really be somewhere in /usr
for a proper installed system - it is somewhere to which only root can write and not my user. Thus, we cannot write any output there. The builtin modules etc are in there though!
I found sysRoot
confusing, like I have managed to learn that it is a subdirectory to sysPath
(I sort of want to think the root is higher up) but then I can never remember whether sysRoot
is the root of the lib files or the code (.c / .h / .ty)... so I propose we replace it with sysMod
which is clearer, at least to me. Similarly we have sysLib
for the lib directory. Since #43 we already put project library output in a separate libActonProject.a and libActon.a contains the system builtin / included libraries. Thus, for this we just need to change so we put libActonProject.a in projLib
. When building we need to add (-L
) both the projLib
and sysLib
directories to ensure we can find libActonProject.a
and libActon.a
. Cgen output goes in projMod
instead of sysRoot
/ sysMod
like now. We obviously need to include both when building so we can find the right .h
and .ty
files.
I'm not entirely sure about the meaning of topMod and modPrefix but I think I wrangled them right in my POC.
projPath ++ "/src"
--path
argument to --syspath
to further clarify what it is forsysPath
default to a compile time value which depends on where we intend to install something for a particular platformsysLib
is sysPath ++ /lib
sysMod
is sysPath ++ /modules
projLib
is projPath ++ /lib
projMod
is projPath ++ /modules
I wrote above that the structure of the Acton system should be defined at compile time, like we define sysPath. On a Debian (like most Linuxes) this would prolly be /usr/lib/acton
, so if we compute sysLib
and sysMod
based on that, we'd end up with like:
/usr/bin/actonc
/usr/lib/acton/lib/
/usr/lib/acton/modules/
It's a little weird to have a lib
directory nested under our under /usr/lib/acton
but they're sort of different libs, like this isn't the "compile any C library on your system with these lib files", so our lib is different. Yet, I do think the acton
dir belongs in /usr/lib
. There are many things in there that aren't C libraries we can link to and it seems our stuff belongs there. Alternative is like /usr/share
but there's mostly other stuff in there?
I explicitly want to say that I don't think it's an option to place our libs in /usr/lib
and our generated C code (.h header files) in /usr/include
. If you only were to look at the type of file, like "this is a .h file" you might be tempted to put it in /usr/include
but our files are not for generic C use - they are specific to Acton and thus do not belong there.
On FreeBSD I think the equivalent is:
/usr/local/bin/actonc
/usr/local/lib/acton/lib/
/usr/local/lib/acton/modules/
We notice that the paths relative to each other and actonc
are actually the same, so it might be that we could keep the current approach of determining sysPath based on the location of actonc
- just that we also assume a structure, specifically:
bin/actonc
lib/acton/lib/
lib/acton/modules/
so like
sysPath = joinPath [ takeDirectory $ takeDirectory execDir, "lib", "acton" ]
we could make this work in the acton source repo just by moving files around a bit, then it'd always be the same! Simple!? Or we just supply --syspath
when invoked in the development repo...
The current make targets aren't properly declarative. The offending targets are mostly those that add something to the libActon archive, like in rts/Makefile
we find:
rts.o: rts.c rts.h
cc $(CFLAGS) -g -Wno-int-to-void-pointer-cast \
-pthread \
-c -O3 rts.c
ar cr ../lib/libActon.a rts.o
cc $(CFLAGS) -c empty.c
ar cr ../lib/libcomm.a empty.o
ar cr ../lib/libdb.a empty.o
ar cr ../lib/libdbclient.a empty.o
as can be seen, it writes to ../lib/libActon.a and other archives in ../lib/. A proper declarative target would instead define a target for how to build lib/libActon.a
and have it depend on the constituent parts. This way out of date dependency calculation will actually work. Right now the only way to be safe is to do a make clean
first and then recompile the whole shebang which is exceedingly annoying
When compiling Acton itself and the Acton RTS, libActon.a
is produced. Later when we use actonc
to compile programs written in Acton, it will place the resulting modules in the libActon.a
archive, mixing up things that were delivered as part of Acton and what has been locally compiled. We should have a clear division of what is part of Acton and what has been locally compiled using Acton.
Need some basic functions to get random integer in a range etc.
Must be thread safe though!
We should fix (neo?)vim support for Acton through a language server (see #190)!
actonc
should automatically detect the acton system path based on:
The configuration file can contain various project settings. I think this is sort of similar to how Rust's cargo works, e.g.:
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
when creating a new project, a top level project config file is generated (Cargo.toml
) that contains project settings. Then there's a standardised project directory structure.
actonc
currently assumes its own location is at the root of the system. This requires a copy of actonc with every Acton project. This in itself isn't overly bad, roughly similar to a Python virtualenv with its own interpreted (got to guarantee not just library version but also the interpreter!). However, like Python virtualens are an optional thing, I think it should be optional for Acton. I imagine that after you've installed acton, the compiler will live in /usr/bin along with its required supportive infrastructure in /usr/lib/acton or so. That should be enough to compile Acton programs.
@nordlander and I have talked about this or at least adjacent topics before and he convinced me about certain points - at least he had thought more about the topic than I had, at the time. I believe the core concept @nordlander wants is to avoid "path hell", where the compiled output will vary based on what paths happen to be in the hypothetical "ACTON_PATH". It seems to me that this boils down to not having a PATH for searching for libraries etc. Instead we want a package tool that resolves libraries for us, downloading specific version as necessary etc. I agree with this, but I think it is largely orthogonal to the location of actonc
. We should not need to have a copy of actonc in itself. We can still consider actonc
a package that should be versioned, or rather than in the project config, we can specify a particular version of actonc
to use... but I don't think that needs to mean that it has to live in the root of project directory.
Haskell stack uses a specific resolver to resolve what versions of packages to use etc. The resolver also dictates the haskell compiler version. Stack downloads stuff to /.stack - so it is possible to have multiple versions installed, but they are not installed per project but rather in a shared location. This seems like a sane design. To allow it for acton, we need to decouple the installed location of acton with the project directory.
This is relevant right now because I want to create some form of "release" of Acton that can be downloaded by users wanting to try it out. The shape and form of that release will need to look different depending on how this works.
I think it would be cool to be able to await an async message but give a time limit for how long we wait. Discuss!
The README.md says to download Acton, extract and then run examples/helloworld... it's just that we don't include that in the release... so either include it or give different instructions?
This program:
actor main(env):
var foo = 1
var bar = foo * 0.5
def finish():
env.exit(0)
after foo: finish()
results in this compilation error:
******************** Type error
Cannot solve 'w$7' : 'T$5' (__builtin__.Number), 'w$12' : 'T$5' < 'T$9', 'T$5' < __builtin__.int, 'w$16' : 'T$9' (__builtin__.Times['T$11']), 'w$15' : 'T$13' < 'T$11', 'w$14' : 'T$13' (__builtin__.RealFloat)
It seems the compiler can't solve this where foo
needs to be of type Times
for the after:
statement (I guess) and also being a float when assigning variable bar
(since it multiplies by 0.5, which is a float). I can make it work by explicitly casting foo to a float in the assignment of bar:
actor main(env):
var foo = 1
var bar = float(foo) * 0.5
def finish():
env.exit(0)
after foo: finish()
However, I think it should be possible to do this, i.e. cast foo
to an int explicitly and then rely on the system understanding that an integer can be cast as a float and do that for me implicitly.
actor main(env):
var foo = 1
var bar = int(foo) * 0.5
def finish():
env.exit(0)
after foo: finish()
It returns another unsolvable type error though:
******************** Type error
Cannot solve 'T$15' < __builtin__.int, 'w$16' : 'T$15' (__builtin__.RealFloat)
Here's a basic scenario for the live system upgrade. I think it can serve as an example for a discussion on the topic.
This is a simple program, version 1:
actor Counter(foo):
var a = 0
def get():
a += 1
return "%s: %d" % (foo, a)
actor main(env):
var counter = Counter("banana")
def _work():
msg = counter.get()
print(msg)
after 1: _work()
_work()
We decide to rename the variable a
to b
so that the program becomes:
actor Counter(foo):
var b = 0
def get():
b += 1
return "%s: %d" % (foo, b)
actor main(env):
var counter = Counter("banana")
def _work():
msg = counter.get()
print(msg)
after 1: _work()
_work()
We want the running program to be upgraded to the new version without losing its state. It is likely not possible to infer that the variable called b
has the same purpose that the variable previously called a
had, so mapping the old value in a
to b
becomes a manual upgrade task. The upgrade function could look like:
def upgrade(old, new):
new.b = old.a
return new
The upgrade function is handed two arguments, the first is the old actor instance and the second is the new actor instance, which has already been instantiated for us. We are expected to return the new actor instance. If there are parts of an upgrade (or the whole upgrade) that can be done automatically, then it is just a matter of returning new
. In this case, something has automatically mapped the old variable foo
to the new variable foo
. If manual mapping are required, then that code needs to be filled in and... return new. It is naturally also possible to instantiate your own new actor instance. new
is only provided through an argument as a matter of convenience - in fact, this way, we could have a default upgrade function that would run when none is manually built.
after X
for ourselves or are just really busy?Right now the tar balls available in https://github.com/actonlang/acton/releases/tag/tip include the version, like acton-darwin-x86_64-0.4.0.tar.bz2
. This makes it impossible to get the latest tip release with a stable URL. It'll be even worse after #63.
I'm not sure if it is possible to alias / symlink, but given the (currently) small size of the acton system we can just upload it twice, so it is also available as acton-linux-x86_64.tar.bz2
- it is still possible to identify exactly which tip build it is using actonc --version
.
This should make it possible to always get the latest tip by doing like wget https://github.com/actonlang/acton/releases/download/tip/acton-linux-x86_64.tar.bz2
As discussed in meeting today; Investigate why acton programs take so long to start up with the database backend.
For example, try the simple count program we have: https://github.com/actonlang/acton/blob/main/examples/count.act
A description for how to run the database and program is in the header of that file!
The slow function is remote_read_full_table_in_txn
at https://github.com/actonlang/acton/blob/main/rts/rts.c#L1329
Why is it slow on an empty (just started) system?
Why is it slow for a small system, like when we just have a single actor, shouldn't this run in "no time at all"?
Is there a way to reference my own actor? Like self
? If I give a callback to another actor I can just pass my method, but sometimes, like if the other actor should call multiple different callbacks, it could be easier to just pass a reference to my actor instead and have the other actor call methods on myself.
This is particularly difficult when we are the root actor, since we haven't created ourselves and thus do not have any handle on ourselves. For other actors there is at least a reference somewhere, like in the root. I suppose we could pass that reference to the actor itself so it would have a reference (stupid, but could work).
After the split of binary output now being written to the dist
directory, we should place the source files of modules in the modules directory! At least for the simple modules where names align, like for time where there's a time.act
, time.h
and time.c
. numpy is more complicated so I guess that one can remain as-is.
It is idiomatic Python to use _
as a dummy / throwaway variable. In Acton, it doesn't work:
kll@Boxy:~/terastream/acton/test$ ../actonc --root main pinger.act && ./pinger
******************** Syntax error
pinger.act:25:11:
|
25 | _ = env.exit(1)
| ^^^
unexpected "= e"
expecting "def", ':', or comma
I tried to assign the return value from env.exit()
as to get around #22 but trying to assign to _
fails with the above error. I don't think it should!? I'll classify as bug for now. If this is per design we can change classification.
I enabled a bunch of backend tests (I was really restructuring Makefiles) but didn't look much at the output... heh. Just saw this:
./actor_ring_tests_local
usage: ./actor_ring_tests_local <no_actors> <no_enqueues>
./actor_ring_tests_remote
usage: ./actor_ring_tests_remote <hostname> <port> <no_actors> <no_enqueues>
We obviously need to provide some sensible arguments here...
This program fails
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = thing.foo()
if 1 > 0:
break
env.exit(0)
like this:
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main for-break.act
/home/kll/terastream/acton/modules/test/for-break.c: In function ‘test$_$for_45_break$$l$5c$7cont’:
/home/kll/terastream/acton/modules/test/for-break.c:126:9: error: break statement not within loop or switch
126 | break;
| ^~~~~
/usr/bin/ld: /tmp/ccyWB2dw.o: in function `$ROOTINIT':
/home/kll/terastream/acton/modules/test/for-break.root.c:3: undefined reference to `test$_$for_45_break$$__init__'
/usr/bin/ld: /tmp/ccyWB2dw.o: in function `$ROOT':
/home/kll/terastream/acton/modules/test/for-break.root.c:6: undefined reference to `test$_$for_45_break$$main$new'
collect2: error: ld returned 1 exit status
kll@ThinkYoga:~/terastream/acton/test$
I think something special happens when an actor is involved, like thing
in our code. If we remove that or replace it with a simple variable assignment, everything works just fine:
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = "hello"
if 1 > 0:
break
env.exit(0)
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main for-break.act
kll@ThinkYoga:~/terastream/acton/test$ echo $?
0
kll@ThinkYoga:~/terastream/acton/test$
Similarly moving the break out of a condition works:
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = "hello"
break
env.exit(0)
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main for-break.act
kll@ThinkYoga:~/terastream/acton/test$ echo $?
0
kll@ThinkYoga:~/terastream/acton/test$
Need sub second precision here!
Just noticed that the example I reference in README.md in #59 is missing! Need to add examples/helloworld.act
- it exists locally on my machine!
I want to make sure we statically link the final binary that actonc produces. Check and fix if necessary!
We now run backend/db_unit_tests in CI but there's at least two problems. One test case is reported as failing, see below:
./db_unit_tests
Test create_schema - OK
Test populate_db - OK
Test test_search_pk - OK
Test test_search_pk_ck1 - OK
Test test_search_pk_ck1_ck2 - OK
Test test_search_column - OK
Test test_search_index - OK
Test test_update - OK
Test test_delete_col - OK
Test test_delete_pk_ck1_ck2 - OK
Test test_delete_pk_ck1 - OK
Test test_delete_pk - OK
Test repopulate_db - OK
Test test_delete_index - FAILED
Test test_range_search_pk_copy - OK
Test test_range_search_pk_ck1 - OK
Test test_range_search_pk_ck1_ck2 - OK
Test test_range_search_index - OK
However, this isn't reflected in the return code of the db_unit_tests
program - it should exit with a non-0 exit code!
Also, the test_delete_index test should be fixed, or well, the code that test_delete_index
is testing!
We currently support kqueue, which means the RTS works out of the box on BSDish platforms like OS X. On Linux, we use libkqueue, which is a compatibility shim so that programs written for kqueue can work on Linux (which is mapped to epoll on Linux).
What should be our ultimate plan? I think we have a few different options
Without really knowing much of anything here, one hybrid choice appeals to me:
libuv supports many things, so it might be that certain operations could be implemented with less code using libuv while we use the native APIs for the operations where it really matters, i.e. in hot loops. For example:
Reading:
There are some tests in backend/
but they aren't called from any current make target. Make it so! The tests should be run in CI!
Here's my program:
actor Foo():
def ping():
return "pong"
actor main(env):
var actors = [Foo()]
for act in actors:
act.ping()
env.exit(0)
Which results in this compilation error:
******************** Compilation error
8:9-11
|
8 | act.ping()
| ^^^
Name act is not in scope
I can work around this by doing an assignment, like so:
actor Foo():
def ping():
return "pong"
actor main(env):
var actors = [Foo()]
for act in actors:
a = act.ping()
env.exit(0)
but I don't think that should be necessary. Another way is to wrap it in another local method:
actor Foo():
def ping():
return "pong"
actor main(env):
var actors = [Foo()]
def ping_actor(act):
act.ping()
for act in actors:
ping_actor(act)
env.exit(0)
I just think it's clearer... and better.
Not a very high priority task, but should attempt to move to a newer stackage resolver just to keep up...
I don't know how to see old runs of a GitHub Action for a PR but for #82 I had two failures of a database related test and IIRC it was queue_unit_tests. We should try to reproduce somehow... I had to manually re-run the workflow twice to get it working, so I know something was failing. It was just failing under the Linux job and not on OS X but I'm not sure that has any real bearing, could just be intermittent!?
On the other hand, if we can't reproduce, then not sure what to do. So give this a shot I guess or give up and close issue.
actonc
calls gcc. Should we change this to call cc
instead? On Linux systems they are typically the same but I think on BSD platforms (not OS X), it could be something else?
I just added a very basic test to the repo in https://github.com/svallin/actwo/blob/master/test/ifisnone.act
For some reason, this code is fine:
if f is not None:
pass
else:
print("bad dice")
while trying to reverse the condition borks out:
if f is None:
print("bad dice")
error:
kll@mbp13:~/actwo$ make test
/Library/Developer/CommandLineTools/usr/bin/make -C test
/Library/Developer/CommandLineTools/usr/bin/make ifisnone
../actonc ifisnone.act
In file included from /Users/kll/actwo/modules/test/ifisnone.c:1:
/Users/kll/actwo/modules/test/ifisnone.h:9:42: error: unexpected type name '$Number': expected identifier
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:9:51: error: unexpected type name 'test$ifisnone$$main': expected identifier
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:9:72: error: unexpected type name '$Env': expected identifier
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:9:78: error: unexpected type name '$Cont': expected identifier
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:9:85: error: unexpected type name '$RFile': expected identifier
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:9:31: error: a parameter list without types is only allowed in a function
definition
$R test$ifisnone$$l$1c$1cont ($Identity, $Number, test$ifisnone$$main, $Env, $Cont, $RFile);
^
/Users/kll/actwo/modules/test/ifisnone.h:14:54: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
$NoneType (*__init__) (test$ifisnone$$l$2lambda, $Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.h:23:5: error: unknown type name '$Identity'
$Identity w$14;
^
/Users/kll/actwo/modules/test/ifisnone.h:54:66: error: unexpected type name '$Number': expected identifier
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.h:54:75: error: unexpected type name 'test$ifisnone$$main': expected identifier
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.h:54:96: error: unexpected type name '$Env': expected identifier
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.h:54:102: error: unexpected type name '$Cont': expected identifier
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.h:54:55: error: a parameter list without types is only allowed in a function
definition
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity, $Number, test$ifisnone$$main, $Env, $Cont);
^
/Users/kll/actwo/modules/test/ifisnone.c:2:31: error: unknown type name '$Identity'
$R test$ifisnone$$l$1c$1cont ($Identity w$14, $Number w$26, test$ifisnone$$main __self__, $Env env, $Cont c$con...
^
/Users/kll/actwo/modules/test/ifisnone.c:17:79: error: unknown type name '$Identity'
$NoneType test$ifisnone$$l$2lambda$__init__ (test$ifisnone$$l$2lambda p$self, $Identity w$14, $Number w$26, tes...
^
/Users/kll/actwo/modules/test/ifisnone.c:26:5: error: use of undeclared identifier '$Identity'
$Identity w$14 = p$self->w$14;
^
/Users/kll/actwo/modules/test/ifisnone.c:31:38: error: use of undeclared identifier 'w$14'
return test$ifisnone$$l$1c$1cont(w$14, w$26, __self__, env, c$cont, p$1);
^
/Users/kll/actwo/modules/test/ifisnone.c:56:55: error: unknown type name '$Identity'
test$ifisnone$$l$2lambda test$ifisnone$$l$2lambda$new($Identity p$1, $Number p$2, test$ifisnone$$main p$3, $En...
^
/Users/kll/actwo/modules/test/ifisnone.c:67:5: error: use of undeclared identifier '$Identity'
$Identity w$14 = (($Identity)$IdentityOpt$new());
^
/Users/kll/actwo/modules/test/ifisnone.c:68:106: error: use of undeclared identifier 'w$14'; did you mean 'w$26'?
return $AWAIT(env->$class->openR(env, to$str("ifnotnone.act")), (($Cont)test$ifisnone$$l$2lambda$new(w$14, w$26...
^~~~
w$26
/Users/kll/actwo/modules/test/ifisnone.c:66:13: note: 'w$26' declared here
$Number w$26 = (($Number)$Integral$int$new());
^
1 warning and 19 errors generated.
kll@mbp13:~/actwo$
We should make Acton available via homebrew. I think that means we provide a "cask" tap!!!
This makes sense once we've gotten #44 fixed. We can't have Acton installed somewhere and write the output of actonc to that acton system directory.
Fix the test so it doesn't segfault I guess!? Or is it a valid test at all?
I'd like to produce a debian package of the Acton system so it is even easier to install!
This probably only makes sense after #44
I tried to run:
actonc --version
I expected to see the version information
actonc
complains about a missing FILE argument.
kll@ThinkYoga:~/terastream/acton$ ./actonc --version
Missing: FILE
Usage: actonc [--parse] [--kinds] [--types] [--sigs] [--norm] [--deact] [--cps]
[--llift] [--hgen] [--cgen] [--verbose] [--version] [--stub]
[--path TARGETDIR] [--root ARG] FILE
Compile an Acton source file with recompilation of imported modules as needed
kll@ThinkYoga:~/terastream/acton$
It's because FILE is a mandatory argument and not optional, so this is perfectly natural.
It's funny that I added this --version
argument and apparently I must have only tested by like appending --version
to some existing command that already had the file specified. I cannot have tried just running actonc --version
:P
tip releases have a version number that includes the date and time they were built, like we are currently on v0.4.0 so a tip built now would get a version of 0.4.0.2021.08.05.12.15.37 (my local time - should it be UTC :/). This is reflect in actonc --version
, however, the tar balls available via https://github.com/actonlang/acton/releases/tag/tip do not include the date and time in the filename. I think they should!
Hmm, so I was a little perplexed over how my program apparently did things after I called env.exit(0)
, which I suppose must be because it will run async since there is no assignment happening. Changing to
foo = env.exit(0)
fixes it by exiting immediately as I expected.
Is this good? We've talked about async before, what to do implicitly and what to do explicitly (i.e. require keywords). Not sure if there is something new to be said. Maybe just complete our documentation and move on ;)
The tip release is updated for every CI run on the main branch. We upload new assets / artifacts and update the release note. The release date however stays the same, ie it is set when the tip release is created - not when it is updated. This irks me because all the content is fresh and I want the date to reflect that. It also affects the order in which it appears on the release page and I think it should go at the top.
I think the only way to fix this is to simply remove the tip release and create it from the Github Action workflow we use.
We should implement a language server for Acton and build an emacs-mode in Emacs that makes use of it.
Depends on #190
The code:
actor Foo():
def ping():
return "pong"
actor main(env):
print(Foo().ping())
var a = Foo().ping()
print(a)
env.exit(0)
The output is:
<$Msg object at 0x7fbc41504200>
pong
whereas I would expect to just see:
pong
pong
We run ./queue_unit_tests
in CI / as part of tests and it shows an error:
...
Test join_consumer_thread - OK (0)
Test join_consumer_replay_thread - OK (0)
Test enqueue - OK (0)
Test dequeue - OK (0)
Test read_head - OK (0)
Test consume - OK (0)
Test dequeue - OK (0)
Test read_head - OK (0)
Test dequeue - FAILED (0)
Test read_head_replay - OK (0)
BACKEND: Queue 0/0 deleted
Test delete_queue - OK (0)
queue_unit_tests
to reflect that individiual tests are failingactonc uses C as an intermediate representation. That means after we've done compiling an .act program to C we run gcc to compile C to a binary and then include than in a library file that we can finally link together to form a program.
Some Acton programs do not currently compile correctly. They are valid Acton syntax, so they will pass the first compilation step but gcc will barf and return some error. However, actonc doesn't honor that return code and continues anyway.
Here's an example application that fails in that way:
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = thing.foo()
if 1 > 0:
break
env.exit(0)
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main for-break.act
/home/kll/terastream/acton/modules/test/for-break.c: In function ‘test$_$for_45_break$$l$6c$5cont’:
/home/kll/terastream/acton/modules/test/for-break.c:190:9: error: break statement not within loop or switch
190 | break;
| ^~~~~
/usr/bin/ld: /tmp/cc5uOMTi.o: in function `$ROOTINIT':
/home/kll/terastream/acton/modules/test/for-break.root.c:3: undefined reference to `test$_$for_45_break$$__init__'
/usr/bin/ld: /tmp/cc5uOMTi.o: in function `$ROOT':
/home/kll/terastream/acton/modules/test/for-break.root.c:6: undefined reference to `test$_$for_45_break$$main$new'
collect2: error: ld returned 1 exit status
kll@ThinkYoga:~/terastream/acton/test$ echo $?
0
kll@ThinkYoga:~/terastream/acton/test$
The resulting behavior can give quite subtle errors. When developing acton programs and iterating on the code, I can first have a working program, let's say the above program first looked like this:
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = thing.foo()
print("Hello")
env.exit(0)
(i.e. no break statement nested under a condition)
This works correctly:
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main foo.act && ./foo
Hello
Now let's add back the break:
actor Thing():
def foo():
return 1
actor main(env):
var thingies = [Thing()]
for thing in thingies:
bar = thing.foo()
print("Hello")
env.exit(0)
recompiling & running yields:
kll@ThinkYoga:~/terastream/acton/test$ ../actonc --root main foo.act && ./foo
/home/kll/terastream/acton/modules/test/foo.c: In function ‘test$foo$$l$5c$7cont’:
/home/kll/terastream/acton/modules/test/foo.c:127:9: error: break statement not within loop or switch
127 | break;
| ^~~~~
Hello
kll@ThinkYoga:~/terastream/acton/test$
that is, the compilation fail... and correctly does not output the foo binary nor the library in libActon but as we get return code 0 we happily continue to run.
I want to test Acton on other CPU architectures. Good to ensure things work on big / little endian systems etc
I believe the following is true:
foo.bar()
, then it is called asynchronously, whereas if the return value is assigned, like a = foo.bar()
then the actor method call is synchronous@nordlander is the above true? Also realized while writing this, that this is not specific to when wrapping C libraries - this is the generic Acton sync behavior, but I guess it is somehow extra relevant to point out when implementing a library.
I know it is possible to explicitly do something async or sync by adding await
/ async
keywords at the call site. Is it possible to change the sync/async behaviour by specifying something at the function definition? No, right? I think I've asked this before but have forgotten.
Should add this to the guide!
I need a time function of some sort in order to build benchmarks for Acton. Sure, I can measure externally from Acton but it would be so much better with a timing function. We don't need to implement a complete datetime
style module. I'm talking about like simple UNIX timestamps - as long as they have enough precision!
kll@ThinkYoga:~$ python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.time()
1626764135.0713706
>>> time.time_ns()
1626764135940527153
>>>
so maybe build a time
module but only implement the time()
or time_ns()
function!?
I don't think there are any special Acton concerns here, like talking to an external system. If an actor is migrated between two different compute nodes, then calling time.time()
might give surprising results in case the machines time aren't synced up. Like the clock going backwards... but I think that can already happen, right? No guarantee of monotonic time.
I'd like to add in a BSD so we build and test not just for Linux and OS X.
https://github.com/marketplace/actions/freebsd-vm allows running stuff on FreeBSD - seems easy enough.
Since a while back we build the RTS and have a compile time option (WITH_BACKEND
) for the RTS to enable the use of the distributed database (DDB). The address and port to use is hard coded to localhost:32000.
We need to make it runtime configuration whether the RTS should use the distributed database backend or not as well as what host and port to connect to.
With this change, we can entirely remove the WITH_BACKEND flag and just have run time flags. It will greatly simplify experimentation with the database backend, in particular since the idea is that we will make binary releases of Acton available, so recompiling with an extra build flag would be a lot of work compared to downloading a readily available release.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.