My photo

Mildred's Website

Tags:
My avatar

GoogleTalk, Jabber, XMPP address:
mildred@jabber.fr


GPG Public Key
(Fingerprint 197C A7E6 645B 4299 6D37 684B 6F9D A8D6 9A7D 2E2B)

Articles

Articles from 31 to 40

Tue 22 Mar 2011, 10:10 AM comp en freedombox

Attention: this post contains wrong information. What I discovered wasn't a way tu publish services to a DNS server but publish local workstations to the DNS.

Following my previous post, I wondered how to update the DNS server from Avahi. I was not alone. I found a script that could be run as a cron job that does the job. The next step is to use Avahi notifications instead of pooling every minute.

Thanks to leica

edit: probably a better solution would to still use mDNS over unicast DNS (wide area). See a post from Lennart Poettering.

Wed 23 Mar 2011, 09:21 AM comp en freedombox

Suppose we want to have an E-Mail server on the freedombox. We need connectivity for SMTP, the ability to accept inbound connections. Which is impossible behind a NAT.

For E-Mails we also need a MX record in the DNS ... This is a problem if the network is completely hostile. In which case, the only solution is to have a somewhat P2P DNS database shared on freedombox. Access would then not be possible from the Internet.

Now, more likely, we are only going to have access to a dynamix DNS, which is fine. The DNS would store records A, AAAA and MX. Perhaps some others. Still, we need not to rely on them too much and have the ability to communicate from freedombox to another even if there is no DNS for us.

So ... it comes down to the firewall and NAT restrictions.

I suppose we could:

  • First, autoconfigure IPv4 and IPv6

  • Try opening NAT ports using UPnP

  • Check the IP connectivity. We suppose IPv6 is accessible from the Internet and we look to see if the IPv4 is in a range that is routable (not in a private non-routable range).

    Additionally, we could ask a service on the Internet to test our connectivity if such a service is available. Both for IPv4 and IPv6.

  • If we don't have an IPv6 connectivity, open a tunnel to the IPv6 Internet. Either Toredo or a manually configured tunnel if available.

  • Update our DNS record

So now, we have at least IPv6 available ... and we can at least communicate with the v6 Internet.

Tue 29 Mar 2011, 02:34 PM comp en lisaac

Inspired from ruby #Array:

Section Header

  + name := PIPE(E);

Section Private

  + blc :{;BOOLEAN,E};

Section Public

  - create blc_:{;BOOLEAN,E} :SELF <-
  (
    blc := blc_;
    Self
  );

  - read :(BOOLEAN,E) <- blc.value

  - map blc:{E;X} :PIPE(X) <-
  ( // Upvalue Self
    PIPE(X).clone.make {
      + have_e :BOOLEAN;
      + e :E;
      (have_e, e) := Self.read;
      have_e.if {
        e := blc.value e;
      };
      have_e, e
    }
  );

  - select blc:{E;BOOLEAN} :PIPE(E) <-
  ( // Upvalue Self
    PIPE(E).clone.make {
      + have_e :BOOLEAN;
      + e :E;
      (have_e, e) := Self.read;
      have_e.if {
        blc.value e.if_false {
          have_e := FALSE;
        };
      };
      have_e, e
    }
  );

  - flatten_1 :PIPE(X) <-
  ( // Upvalue Self, buffer
    + buffer :PIPE(X);
    PIPE(X).clone.make {
      + have_e, have_x :BOOLEAN;
      + e :E;
      + x :X;
      buffer.is_null.if_false {
        (have_e, e) := buffer.read;
        have_e.if_false {
          buffer := NULL;
        };
      };
      buffer.is_null.if {
        (have_e, e) := Self.read;
        have_e.if {
          (buffer ?= e).is_null.if_false {
            (have_x, x) := buffer.read
            // TODO: cas où have_e = FALSE (buffer est vide)
          };
        };
      };
      have_x, x
    }
  );

  - to_array_of_e :ARRAY(E) <-
  ( + result :ARRAY(E);
    + have_e :BOOLEAN;
    + e :E;
    {(have_e, e) := read;
    have_e
    }.while_do {
      result.add_last e;
    };
    result
  );

TODO:

  • Upvalue
  • Syntax improvement (block input variables is too verbose)
  • More typing of parameter types, particurlarly as return values (map return unknown type X)
  • var := bool.if {val1} else {val2}
  • NULL.is_null -> TRUE

Mon 11 Apr 2011, 05:38 PM en fr website

Je vais maintenant gérer mon site avec nanoc. Si vous remarquez des problèmes comme des erreurs 404, merci de me l'indiquer.

This web site is going to be updated using nanoc. If you notice any dead links or anything of the sort, please tell me.

Tue 12 Apr 2011, 04:35 PM comp dev en lisaac lysaac

If you noticed, I started my own Lisaac compiler, called Lysaac and I want to make it a little bit different from Lisaac. I'll try to keep compatibility, but for few things, I might take a different direction.

One of these things is the way prototypes are found.

In Lisaac, you have a complete set of prototypes and when you look for a prototype, it is looked everywhere. This is not desirable. Imagine you are writing a library that requires the prototype FOO. Currently, if FOO is not present in the library, instead of issuing an error, the compiler would take the FOO prototype in the application that use the library. Meaning that the library is effectvely using a pieve of the application code.

I want to take the SmartEiffel approach and separate the source code in few clusters. A cluster is a collection of prototypes. And the prototypes in a cluster can only use the prototype of the same cluster or the prototypes of imported clusters. This solve the above dependancy problem.

A cluster is a directory that contain prototypes in .li files and subdirectories. If a subdirectory do not contain .li files, the sub-subdirectories are not recursively searched. A cluster can import another cluster using a cluster file ending with .cli.

An example of .cli file is as follows:

Section Header

  - name := Cluster LIBFOO;

  - path := ("libfoo-3.14", "../libfoo");

The search paths can be:

  • relative to the .cli file if it starts with .
  • relative to LYSAAC_PATH directories otherwise

LISAAC_PATH defaults to $XDG_DATA_HOME/lysaac/lib:/usr/local/share/lysaac/lib:/usr/share/lysaac/lib.

The search paths would then be for this example:

  • $XDG_DATA_HOME/lysaac/lib/libfoo-3.14
  • /usr/local/share/lysaac/lib/libfoo-3.14
  • /usr/share/lysaac/lib/libfoo-3.14
  • ../libfoo

The parser for these files is being written. Then you can see the complete hierarchy of the project:

$ lysaac src
◆ Root Cluster
│ Cluster in: src
├─◆ LIB (src/lib.cli)
│ │ Cluster in: lib
│ ├─◆ STDLIB (lib/stdlib.cli)
│ │ │ Cluster in: /home/mildred/.local/share/lysaac/lib/stdlib
│ │ ├─◇ STRING (...)
│ │ ├─◇ ABSTRACT_STRING (...)
│ │ ╰─◇ ...
│ ├─◇ LIBC (lib/libc.li)
│ ╰─◇ CSTRING (lib/cstring.li)
├─◇ PARSER (src/parser.li)
├─◇ CLUSTER_ITEM (src/cluster_item.li)
├─◇ ITM_STYLE (src/itm_style.li)
├─◇ LYSAAC (src/lysaac.li)
├─◇ ITM_AFFECT (src/itm_affect.li)
├─◇ ANY (src/any.li)
├─◇ PARSER_CLI (src/parser_cli.li)
╰─◇ CLUSTER (src/cluster.li)

Now, each item in a cluster can be public or private. Public items are available to the users of the clusters whereas private items are restricted to members of the same cluster. To declare a private item, just say:

Section Header

  + name := Private PROTOTYPE;

or

Section Header

  - name := Private Cluster LIBTOTO;

If you want to declare a whole bunch of prototypes private to your cluster, just include them in a private cluster. To do so, you'll need the following files:

  • cluster/my_private_prototypes.cli:

    Section Header
    
      - name := Private Cluster MY_PRIVATE_PROTOTYPES;
    
      - path := "./deps/my_private_prototypes";
      // makes the cluster relative to the .cli file
      // use a deps additional directory to avoid the current cluster to
      // look into deps/my_private_prototypes. deps should not contain any
      // files, just subdirectories.
    
  • cluster/deps/my_private_prototypes/private_proto.li:

    Section Header
    
      + name := Public Prototype PRIVATE_PROTO;
    

Wed 20 Apr 2011, 11:17 AM comp dev lysaac

◆ Root Cluster
│ Cluster in: src
├─◆ LIB (src/lib.cli)
│ │ Cluster in: src/../lib
│ ├─◇ PATH_HELPER (src/../lib/path_helper.li)
│ ├─◇ CSTRING (src/../lib/cstring.li)
│ ╰─◇ LIBC (src/../lib/libc.li)
├─◇ PARSER (src/parser.li)
├─◆ STDLIB (src/stdlib.cli)
│ │ Cluster in: src/../stdlib/standard
│ ├─◆ INTERNAL (src/../stdlib/standard/internal.cli)
│ │ │ Cluster in: src/../stdlib/standard/../internal
│ │ ├─◆ PORTABLE (src/../stdlib/standard/../internal/portable.cli)
│ │ │ │ Cluster in: src/../stdlib/standard/../internal/portable
│ │ │ ├─◇ FLOAT_REAL (src/../stdlib/standard/../internal/portable/number/float_real.li)
│ │ │ ├─◇ FIXED_REAL (src/../stdlib/standard/../internal/portable/number/fixed_real.li)
│ │ │ ├─◇ FLOAT_MAP80 (src/../stdlib/standard/../internal/portable/number/float_map80.li)
│ │ │ ├─◇ SIGNED_INTEGER (src/../stdlib/standard/../internal/portable/number/signed_integer.li)
│ │ │ ├─◇ FLOAT_MAP32 (src/../stdlib/standard/../internal/portable/number/float_map32.li)
│ │ │ ├─◇ UNSIGNED_INTEGER (src/../stdlib/standard/../internal/portable/number/unsigned_integer.li)
│ │ │ ├─◇ FLOAT_MAP64 (src/../stdlib/standard/../internal/portable/number/float_map64.li)
│ │ │ ├─◇ SIGNED_FIXED_REAL (src/../stdlib/standard/../internal/portable/number/signed_fixed_real.li)
│ │ │ ├─◇ NUMERIC (src/../stdlib/standard/../internal/portable/number/numeric.li)
│ │ │ ├─◇ FLOAT_MAP (src/../stdlib/standard/../internal/portable/number/float_map.li)
│ │ │ ├─◇ UNSIGNED_FIXED_REAL (src/../stdlib/standard/../internal/portable/number/unsigned_fixed_real.li)
│ │ │ ├─◇ FILE_INPUT_STREAM (src/../stdlib/standard/../internal/portable/io/file_input_stream.li)
│ │ │ ├─◇ STD_INPUT_OUTPUT (src/../stdlib/standard/../internal/portable/io/std_input_output.li)
│ │ │ ├─◇ FILE_OUTPUT_STREAM (src/../stdlib/standard/../internal/portable/io/file_output_stream.li)
│ │ │ ├─◇ INPUT_STREAM (src/../stdlib/standard/../internal/portable/io/input_stream.li)
│ │ │ ├─◇ OUTPUT_STREAM (src/../stdlib/standard/../internal/portable/io/output_stream.li)
│ │ │ ├─◇ MEMORY (src/../stdlib/standard/../internal/portable/memory/memory.li)
│ │ │ ├─◇ SYSTEM_DETECT (src/../stdlib/standard/../internal/portable/system/system_detect.li)
│ │ │ ├─◇ HASHED_DICTIONARY_NODE (src/../stdlib/standard/../internal/portable/collection/hashed_dictionary_node.li)
│ │ │ ├─◇ COLLECTION (src/../stdlib/standard/../internal/portable/collection/collection.li)
│ │ │ ├─◇ HASH_TABLE_SIZE (src/../stdlib/standard/../internal/portable/collection/hash_table_size.li)
│ │ │ ├─◇ ANY_HASHED_BIJECTIVE_DICTIONARY_NODE (src/../stdlib/standard/../internal/portable/collection/any_hashed_bijective_dictionary_node.li)
│ │ │ ├─◇ ANY_LINKED_LIST_NODE (src/../stdlib/standard/../internal/portable/collection/any_linked_list_node.li)
│ │ │ ├─◇ ANY_AVL_SET_NODE (src/../stdlib/standard/../internal/portable/collection/any_avl_set_node.li)
│ │ │ ├─◇ LINKED2_LIST_NODE (src/../stdlib/standard/../internal/portable/collection/linked2_list_node.li)
│ │ │ ├─◇ ANY_AVL_DICTIONARY_NODE (src/../stdlib/standard/../internal/portable/collection/any_avl_dictionary_node.li)
│ │ │ ├─◇ COLLECTION3 (src/../stdlib/standard/../internal/portable/collection/collection3.li)
│ │ │ ├─◇ SET (src/../stdlib/standard/../internal/portable/collection/set.li)
│ │ │ ├─◇ ANY_TWO_WAY_LINKED_LIST_NODE (src/../stdlib/standard/../internal/portable/collection/any_two_way_linked_list_node.li)
│ │ │ ├─◇ HASHED_SET_NODE (src/../stdlib/standard/../internal/portable/collection/hashed_set_node.li)
│ │ │ ├─◇ ARRAYED_COLLECTION (src/../stdlib/standard/../internal/portable/collection/arrayed_collection.li)
│ │ │ ├─◇ SIMPLE_DICTIONARY (src/../stdlib/standard/../internal/portable/collection/simple_dictionary.li)
│ │ │ ├─◇ DICTIONARY (src/../stdlib/standard/../internal/portable/collection/dictionary.li)
│ │ │ ├─◇ AVL_DICTIONARY_NODE (src/../stdlib/standard/../internal/portable/collection/avl_dictionary_node.li)
│ │ │ ├─◇ AVL_CONSTANTS (src/../stdlib/standard/../internal/portable/collection/avl_constants.li)
│ │ │ ├─◇ ANY_HASHED_SET_NODE (src/../stdlib/standard/../internal/portable/collection/any_hashed_set_node.li)
│ │ │ ├─◇ NATIVE_ARRAY (src/../stdlib/standard/../internal/portable/collection/native_array.li)
│ │ │ ├─◇ AVL_TREE (src/../stdlib/standard/../internal/portable/collection/avl_tree.li)
│ │ │ ├─◇ NATIVE_ARRAY_VOLATILE (src/../stdlib/standard/../internal/portable/collection/native_array_volatile.li)
│ │ │ ├─◇ COLLECTION2 (src/../stdlib/standard/../internal/portable/collection/collection2.li)
│ │ │ ├─◇ ANY_HASHED_DICTIONARY_NODE (src/../stdlib/standard/../internal/portable/collection/any_hashed_dictionary_node.li)
│ │ │ ├─◇ ARRAYED (src/../stdlib/standard/../internal/portable/collection/arrayed.li)
│ │ │ ├─◇ AVL_SET_NODE (src/../stdlib/standard/../internal/portable/collection/avl_set_node.li)
│ │ │ ├─◇ LINKED_XOR_NODE (src/../stdlib/standard/../internal/portable/collection/linked_xor_node.li)
│ │ │ ├─◇ LINKED_LIST_NODE (src/../stdlib/standard/../internal/portable/collection/linked_list_node.li)
│ │ │ ├─◇ AVL_TREE_NODE (src/../stdlib/standard/../internal/portable/collection/avl_tree_node.li)
│ │ │ ├─◇ LINKED_COLLECTION (src/../stdlib/standard/../internal/portable/collection/linked_collection.li)
│ │ │ ├─◇ FS_MIN (src/../stdlib/standard/../internal/portable/file_system/fs_min.li)
│ │ │ ├─◇ STRING_BUFFER (src/../stdlib/standard/../internal/portable/string/string_buffer.li)
│ │ │ ╰─◇ CHARACTER_REF (src/../stdlib/standard/../internal/portable/string/character_ref.li)
│ │ ╰─◆ UNIX (src/../stdlib/standard/../internal/unix.cli)
│ │   │ Cluster in: src/../stdlib/standard/../internal/os_support/unix
│ │   ├─◇ FLOAT_PROCESSOR (src/../stdlib/standard/../internal/os_support/unix/system/float_processor.li)
│ │   ├─◇ SYSTEM (src/../stdlib/standard/../internal/os_support/unix/system/system.li)
│ │   ├─◇ CLOCK (src/../stdlib/standard/../internal/os_support/unix/system/clock.li)
│ │   ├─◇ ENVIRONMENT (src/../stdlib/standard/../internal/os_support/unix/system/environment.li)
│ │   ├─◇ SYSTEM_IO (src/../stdlib/standard/../internal/os_support/unix/system/system_io.li)
│ │   ├─◇ PROCESSOR (src/../stdlib/standard/../internal/os_support/unix/system/processor.li)
│ │   ├─◇ EVENT_SYSTEM (src/../stdlib/standard/../internal/os_support/unix/video/event_system.li)
│ │   ├─◇ KEYBOARD (src/../stdlib/standard/../internal/os_support/unix/video/keyboard.li)
│ │   ├─◇ TIMER (src/../stdlib/standard/../internal/os_support/unix/video/timer.li)
│ │   ├─◇ VIDEO (src/../stdlib/standard/../internal/os_support/unix/video/video.li)
│ │   ├─◇ MOUSE (src/../stdlib/standard/../internal/os_support/unix/video/mouse.li)
│ │   ├─◇ FILE_UNIX (src/../stdlib/standard/../internal/os_support/unix/file_system/file_unix.li)
│ │   ├─◇ FILE_SYSTEM (src/../stdlib/standard/../internal/os_support/unix/file_system/file_system.li)
│ │   ├─◇ ENTRY_UNIX (src/../stdlib/standard/../internal/os_support/unix/file_system/entry_unix.li)
│ │   ├─◇ DIRECTORY_UNIX (src/../stdlib/standard/../internal/os_support/unix/file_system/directory_unix.li)
│ │   ├─◇ BMP_LINE_ASCII (src/../stdlib/standard/../internal/os_support/unix/video_ascii/bmp_line_ascii.li)
│ │   ├─◇ BITMAP_ASCII (src/../stdlib/standard/../internal/os_support/unix/video_ascii/bitmap_ascii.li)
│ │   ├─◇ VIDEO (src/../stdlib/standard/../internal/os_support/unix/video_ascii/video.li)
│ │   ╰─◇ PIXEL_ASCII (src/../stdlib/standard/../internal/os_support/unix/video_ascii/pixel_ascii.li)
│ ├─◇ STD_ERROR (src/../stdlib/standard/io/std_error.li)
│ ├─◇ COMMAND_LINE (src/../stdlib/standard/io/command_line.li)
│ ├─◇ IO (src/../stdlib/standard/io/io.li)
│ ├─◇ STD_INPUT (src/../stdlib/standard/io/std_input.li)
│ ├─◇ STD_OUTPUT (src/../stdlib/standard/io/std_output.li)
│ ├─◇ TIME (src/../stdlib/standard/time/time.li)
│ ├─◇ DATE (src/../stdlib/standard/time/date.li)
│ ├─◇ HASHABLE (src/../stdlib/standard/property/hashable.li)
│ ├─◇ COMPARABLE (src/../stdlib/standard/property/comparable.li)
│ ├─◇ SAFE_EQUAL (src/../stdlib/standard/property/safe_equal.li)
│ ├─◇ TRAVERSABLE (src/../stdlib/standard/property/traversable.li)
│ ├─◇ OBJECT (src/../stdlib/standard/kernel/object.li)
│ ├─◇ I_DONT_KNOW_PROTOTYPING (src/../stdlib/standard/kernel/i_dont_know_prototyping.li)
│ ├─◇ POINTER (src/../stdlib/standard/kernel/pointer.li)
│ ├─◇ CONVERT (src/../stdlib/standard/kernel/convert.li)
│ ├─◇ REFERENCE (src/../stdlib/standard/kernel/reference.li)
│ ├─◇ BLOCK (src/../stdlib/standard/kernel/block.li)
│ ├─◇ HASHED_DICTIONARY (src/../stdlib/standard/collection/hashed_dictionary.li)
│ ├─◇ ARRAY2 (src/../stdlib/standard/collection/array2.li)
│ ├─◇ AVL_SET (src/../stdlib/standard/collection/avl_set.li)
│ ├─◇ LINKED2_LIST (src/../stdlib/standard/collection/linked2_list.li)
│ ├─◇ ARRAY3 (src/../stdlib/standard/collection/array3.li)
│ ├─◇ ARRAY (src/../stdlib/standard/collection/array.li)
│ ├─◇ ITERATOR (src/../stdlib/standard/collection/iterator.li)
│ ├─◇ FAST_ARRAY3 (src/../stdlib/standard/collection/fast_array3.li)
│ ├─◇ LINKED_XOR_LIST (src/../stdlib/standard/collection/linked_xor_list.li)
│ ├─◇ LINKED_LIST (src/../stdlib/standard/collection/linked_list.li)
│ ├─◇ HASHED_SET (src/../stdlib/standard/collection/hashed_set.li)
│ ├─◇ FAST_ARRAY2 (src/../stdlib/standard/collection/fast_array2.li)
│ ├─◇ FAST_ARRAY (src/../stdlib/standard/collection/fast_array.li)
│ ├─◇ AVL_DICTIONARY (src/../stdlib/standard/collection/avl_dictionary.li)
│ ├─◇ STD_FILE (src/../stdlib/standard/file_system/std_file.li)
│ ├─◇ DIRECTORY (src/../stdlib/standard/file_system/directory.li)
│ ├─◇ ENTRY (src/../stdlib/standard/file_system/entry.li)
│ ├─◇ FILE (src/../stdlib/standard/file_system/file.li)
│ ├─◇ HTTP_SERVER (src/../stdlib/standard/http/http_server.li)
│ ├─◇ HTTP_HEADER (src/../stdlib/standard/http/http_header.li)
│ ├─◇ FALSE (src/../stdlib/standard/boolean/false.li)
│ ├─◇ BOOLEAN (src/../stdlib/standard/boolean/boolean.li)
│ ├─◇ TRUE (src/../stdlib/standard/boolean/true.li)
│ ├─◇ STRING_CONSTANT (src/../stdlib/standard/string/string_constant.li)
│ ├─◇ STRING (src/../stdlib/standard/string/string.li)
│ ├─◇ ABSTRACT_STRING (src/../stdlib/standard/string/abstract_string.li)
│ ╰─◇ CHARACTER (src/../stdlib/standard/string/character.li)
├─◇ CLUSTER_ITEM (src/cluster_item.li)
├─◇ ITM_STYLE (src/itm_style.li)
├─◇ LYSAAC (src/lysaac.li)
├─◇ ITM_AFFECT (src/itm_affect.li)
├─◇ ANY (src/any.li)
├─◇ PARSER_CLI (src/parser_cli.li)
╰─◇ CLUSTER (src/cluster.li)

Fri 22 Apr 2011, 02:13 PM en website

It is now possible to add comments in my blog. Comments are purely in javascript, and you need a recent browser (Firefox 3.5 minimum). This is because I use a cross-domain XmlHttpRequest.

How does it work?

I have a php script somewhere that understand two methods:

  • GET will return all the posted objects associated with a tag passed as a REQUEST_URI (the thing after the question mark in URL)

  • POST will add an item to this series.

All of this in JSON of course, using jQuery.

Now, feel free to comment :)

Sun 24 Apr 2011, 09:13 PM en website

This website is made of static pages. I see two good reasons for that: first, there is no need to recompute endlessly the same information. Then, with static pages, you can leave your web site online forever without having it defaced.

So, how to create a modern web site with that? First, I have to start with what I want:

  • A blog, with the recent posts on the front page
  • An atom feed with the recent posts as well
  • Older posts on other pages
  • Each posts categorized in tags
  • Each tag having a page with posts in it
  • The tags pages must have atom feeds as well
  • And tag pages must be splitted in pages
  • Posts can have comments, anyone can add a comment

This can be achieved using an off-line compiler that creates a hierarchy of HTML files. Many of these compilers exists, I choose nanoc, but I had to customize it, mostly using nanoc3_blog.

Some features can be easily provided:

  • The atom feed can be created using a helper included in nanoc
  • The tags can be easily crafted using page attributes.
  • Tag pages can be created on the fly using a hand-made helper
  • Pagination can be done the same way

Now, a word about design:

Pagination, this is frowned upon by the nanoc author as demonstrated on the guide:

First, a word of caution: I am not a fan of paginating items. Even though pagination is fairly easy to do in nanoc, I recommend not doing it, for one specific reason. Every time an object is added to a paginated collection, one object shifts from one page to the next. When a paginated page is bookmarked, it may show entirely different content a month later, and when a paginated page turns up as a result on a search engine, it may no longer contain the content that the person was looking for anymore. To avoid these issues, I recommend creating separate pages for each category, tag or year. Having said all this, I’ll nonetheless show you how to do pagination in nanoc, so you can get an idea of how it can be done.

In order to avoid having the object shifting pages, the most simple solution is to have the pages remain static. Say you want to have 10 items per page, the first page starts empty until it has 10 items. When an 11th item is added, a second page is created with one element. For blogs, it might seem to be in reverse order, but for archives, this is not a bad solution.

The pagination system must be uniform and available for any page on the website. This way, the index page and tag page can have the same pagination system. The pagination system must also support creating atom feeds. This way, we can have a feed for the whole blog and a feed per tag. In nanoc, this can be done using alternative representations for an item.

Comments, can be done using JavaScript. For a first solution, this is acceptable, even though having a solution working with user agents without javascript is a goal. For this, we can use jQuery and XmlHttpRequest. Because the server only provides static pages, XmlHttpRequest, having a same-origin policy, will refuse to work. There are several solutions:

  • Proxy the foreign resource on the local server. This unfortunately requires mod_proxy which is not available on my server.
  • Another solution is to use Cross Origin Resource Sharing, a W3C recommendation that is still a draft unfortunately, but is started to be implemented.
  • Or to use an iframe with a page of the foreign server, and use the postMessage method to communicate with it, for example with the easyXDM library.
  • Or use HTML <form> element to post the comment on the the API server. The server would then include the comment on the static page and publish it. This unfortunately requires a server with more than a simple php scripting ability. I don't have this.

For now, I am using the XmlHttpRequest solution with the CORS mechanism on the API server to allow communication. Here is where I'd like to move:

  • First, integrate easyXDM for wider browser compatibility, at the cost of the design.
  • Then, use a variation of the static HTML form.

For the static form, here is what i'm thinking of:

  • First, the client can POST the form on the PAI server. If XmlHttpRequest with CORS is available, this can be done using Ajax, else we have to deal with a page reload.
  • The server would store this message on the database with a unique UUID.
  • Other clients can access this message accessing the API server as usual.
  • Frequently, on my computer, I would dump the messages on the API server database and put them in a local yaml file. Comments i'd like to remove can then be removed here.
  • When the site is regenerated, a nanoc helper would read this yaml file and put comments statically in the page. The page would then be published and comments would be available to users without javascript.
  • The script that fetches comments would ignore received comments that are already present statically on the page, based on the UUID.

This way, comments would be available for everyone.

Fri 29 Apr 2011, 09:19 AM comp dev en lisaac lysaac

In Lysaac, I choose to follow the open world assumption, like the majority of programming languages out there, instead of the closed world assumption. There are two main reasons:

  • First, I don't strive at creating an optimizing compiler, not yet at least. Closed world is useful for that, but I don't need it.

  • Second, open world assumption increases the complexity a lot. The Lisaac compiler uses an exponential algorithm, and will always hit a limit with big projects. With an open world, you can partition the complexity.

Because I still believe in global compilation, I decided that my compilation unit would be the cluster instead of the prototype. That is, I'll compile a cluster completely in one object file. That makes it possible to optimize things like private prototypes.

This leaves a big performance problem for BOOLEANs in particular. BOOLEAN, TRUE and FALSE are prototypes in the standard library, and having an open world assumption would require pasing to the if then slot function pointers. I can't realisticly do that.

So, These prototypes could be marked as Inline. They are separated from their cluster and gets compiled in every cluster that uses them. The syntax could be quite simple:

Section Header

  + name := Inline TRUE;

But, because each cluster is then free to compile it as it wants, there is a problem of interoperability. How can you be sure that the TRUE in your cluster is compiled the same way as in the neighbooring cluster you are using. As it is, you can't pass TRUE object around clusters. Very annoying.

The solution would be to encode them and decode them manually. You could have:

Section Header

  + name := Inline TRUE;

Section Feature

  - inline_size :INTEGER := 0;

Take a more interesting example:

Section Header

  + name := Inline Expanded BIT;

  - size := 1;

Section Feature

  - inline_size :INTEGER := 1;
  - encode p:POINTER <-
  (
    p.to_native_array_of BIT.put bit to 0;
  );
  - decode p:POINTER <-
  (
    data := p.to_native_array_of BIT.item 0;
  );

This needs to be refined.

Additionally, .cli files could also contain the Inline keyword. In that case, the cluster it reference will be compiled with the current cluster. That could be useful for private clusters.

Fri 29 Apr 2011, 09:40 AM comp dev en lisaac lysaac

Because I'm using an open world assumption, I need the compiler to generate annotations on units it compiles, so when it sees them again, it knows what it does (or does not) internally.

I was looking at a LLVM video this morning (VMKit precisely) and the person talked about an interesting optimization. What if we could allocate objects in stack instead of the heap. This would save time when creating the object. Then we wouldn't be tempted to avoid creating new objects for fear of memory leaks (there is not garbage collector in lisaac currently) and performance penalty.

This is the same thing as aliased variables in Ada.

An object can be allocated on the stack if:

  • it is not returned by the function.
  • it is not stored on the heap by the function.
  • it is not used in a called function that would store a pointer to this object on the heap.

So, when the compiler compiles a cluster, it has to generate an annotation file containing for each argument in each code slot whether the argument is guaranteed to remain on the stack or if it might be stored on the heap. If an argument is guaranteed to stay on the stack, we can allocate it on the stack. When the function will return, the only instances would be located in the current stack frame.

Page: