Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[doc] adjustement, updates opadoc syntax fix

  • Loading branch information...
commit 87b2c535c3fbf8d93b5a266c71571377662e5d12 1 parent f979a53
Mathieu Barbin authored
View
133 multitub/multitub.opa
@@ -8,7 +8,7 @@
/**
* {1 Multitub}
*
- * In this design pattern, we denote by 'tub' a new connexion. (a new client on the server)
+ * In this design pattern, we denote by 'tub' a new connexion. (a new client on the server).
* For each 'tub', we have 2 sessions, one created on the server side, and one on the client side.
*
* The type of messages handled by theses 2 sessions are the only authorized exchanges
@@ -50,16 +50,16 @@
/**
* The type [Multitub.C.message] should be defined in one of the file of the application.
* It corresponds to the type representing all mesages sent by the server to the
- * client, and the messages sent by some funactions (client private messages)
+ * client, and the messages sent by some funactions (client private messages).
* The handler of the client will perform some actions when it receives
* the messages, e.g. DOM modification / state modification, etc.
**/
// type Multitub.C.message = ??
/**
- * With '@abstract' we denote that user of this lib should not enter the implementation
+ * The user of this lib should not enter the implementation
* of the type, but just using function exported in this file to manipulate values
- * of this type.
+ * of this type. See in particular the function {!Multitub.send_client}
**/
@abstract
type Multitub.C.channel = channel(Multitub.C.message)
@@ -89,9 +89,9 @@ type Multitub.C.channel = channel(Multitub.C.message)
type Multitub.private.S.message = { message : Multitub.S.message } / { set_c_channel : Multitub.C.channel }
/**
- * With '@abstract' we denote that user of this lib should not enter the implementation
+ * The user of this lib should not enter the implementation
* of the type, but just using function exported in this file to manipulate values
- * of this type.
+ * of this type. See in particular the function {!Multitub.send_server}
**/
@abstract
type Multitub.S.channel = channel(Multitub.private.S.message)
@@ -120,45 +120,47 @@ type Multitub.S.channel = channel(Multitub.private.S.message)
* @client Multitub_C : Multitub.C.interface = {{
* ...
* }}
- * ]}
+ * }
+ *
+ * {b init}
+ * Create the internal state of the client.
+ * The initializer is not functionnal because the state of the client
+ * may be imperative, there are no reason to forbid it, e.g. wrt performances
+ * depending on the kind of the application.
+ *
+ * {b on_message}
+ * Handle messages received from the server, or from some funaction in the page.
+ * Possibly, send back some messages to the server asynchronously.
+ * In that case, you must use the function [Multitub.send_server] on the server channel.
+ *
+ * {b page}
+ * Creating the page, on the client side. By convention of the design,
+ * funaction should be tagged @client, and can use one or both of channels,
+ * depending on what does the funaction do.
+ * Example:
+ * {[
+ * @client funaction(s_channel, c_channel, event) =
+ * // depending on the event, send messages to s_channel, or c_channel
+ *
+ * C = {{
+ * page(s_channel, c_channel) =
+ * ...
+ * <div id="myfunaction" onclick={funaction(s_channel, c_channel, _)}/>
+ * }}
+ * }
+ *
+ * <!> The DOM element id 'multitub' is reserved by the application, and should
+ * not be used.
+ *
**/
type Multitub.C.interface('state) = {{
- /**
- * Create the internal state of the client.
- * The initializer is not functionnal because the state of the client
- * may be imperative, there are no reason to forbid it, e.g. wrt performances
- * depending on the kind of the application.
- **/
init : -> 'state
- /**
- * Handle messages received from the server, or from some funaction in the page.
- * Possibly, send back some messages to the server asynchronously.
- * In that case, you must use the function [Multitub.send_server] on the server channel.
- **/
on_message : Multitub.S.channel, 'state, Multitub.C.message -> Session.instruction('state)
- /**
- * Creating the page, on the client side. By convention of the design,
- * funaction should be tagged @client, and can use one or both of channels,
- * depending on what does the funaction do.
- * Example:
- * {[
- * @client funaction(s_channel, c_channel, event) =
- * // depending on the event, send messages to s_channel, or c_channel
- *
- * C = {{
- * page(s_channel, c_channel) =
- * ...
- * <div id="myfunaction" onclick={funaction(s_channel, c_channel, _)}/>
- * }}
- * ]}
- *
- * <!> The DOM element id 'multitub' is reserved by the application, and should
- * not be used.
- **/
page : Multitub.S.channel, Multitub.C.channel -> xhtml
+
}}
/**
@@ -174,36 +176,37 @@ type Multitub.C.interface('state) = {{
* @server Multitub_S : Multitub.S.interface = {{
* ...
* }}
- * ]}
+ * }
+ *
+ * {b init}
+ * Create the internal state of the server.
+ * The initializer is not functionnal because the state of the server
+ * may be imperative.
+ *
+ * {b on_connection}
+ * Some initialization may be necessary once the server knows the client.
+ * This function is not in the [Multitub.C.interface] because of the asymetrie
+ * of the initialization protocol. When we create the client session, the server session
+ * is known.
+ *
+ * This is an extra initialization for the server. In case the server does not need it,
+ * simply does not change the state, as in :
+ * {[
+ * on_connection(_, state) = state
+ * }
+ *
+ * {b on_message}
+ * Handle messages received from the client handler, or from some funaction in the page.
+ * Possibly, send back some messages to the client, in that case, you must
+ * use the function [Multitub.send_client] on the client channel.
+ *
**/
type Multitub.S.interface('state) = {{
- /**
- * Create the internal state of the server.
- * The initializer is not functionnal because the state of the server
- * may be imperative.
- **/
init : -> 'state
- /**
- * Some initialization may be necessary once the server knows the client.
- * This function is not in the [Multitub.C.interface] because of the asymetrie
- * of the initialization protocol. When we create the client session, the server session
- * is known.
- *
- * This is an extra initialization for the server. In case the server does not need it,
- * simply does not change the state, as in :
- * {[
- * on_connection(_, state) = state
- * ]}
- **/
on_connection : Multitub.C.channel, 'state -> 'state
- /**
- * Handle messages received from the client handler, or from some funaction in the page.
- * Possibly, send back some messages to the client, in that case, you must
- * use the function [Multitub.send_client] on the client channel.
- **/
on_message : Multitub.C.channel, 'state, Multitub.S.message -> Session.instruction('state)
}}
@@ -224,7 +227,7 @@ type Multitub.S.interface('state) = {{
* {[
* @server Multitub_S : Multitub.S.interface = ...
* @client Multitub_C : Multitub.C.interface = ...
- * ]}
+ * }
**/
/**
@@ -313,7 +316,7 @@ type Multitub.private.C.state('state) = {
</>
/**
- * The type Multitub.C.message should be 'abstract' (not possible with S3).
+ * The type Multitub.C.message should be 'abstract'
* The server should use this function for sending
* message to the client, and not directly the 'send' function.
**/
@@ -321,7 +324,7 @@ type Multitub.private.C.state('state) = {
send(channel, message)
/**
- * The type Multitub.S.message should be 'abstract' (not possible with S3).
+ * The type Multitub.S.message should be 'abstract'
* The client should use this function for sending
* message to the server, and not directly the 'send' function.
**/
@@ -331,8 +334,8 @@ type Multitub.private.C.state('state) = {
/**
* Creating a [one_page_server]. Use :
* {[
- * server = multitub("Name")
- * ]}
+ * server = Multitub.one_page_server("Name")
+ * }
**/
@server one_page_server(title) = @toplevel.one_page_server(title, multitub_page)
View
10 src/client.opa
@@ -39,11 +39,11 @@ type ClientToken.t = dom
/**
* Sadly, the images used for the grid and the token are not regular
* A aproximantion is :
- * line
- * y = global_margin + margin_y_token + (6 - line) * box_token
- * column
- * x = global_margin + margin_x_token + (column - 1) * box_token
- * But this does not fit perfectly in the resource/grid.png
+ * {b line}:
+ * {[y = global_margin + margin_y_token + (6 - line) * box_token}
+ * {b column}:
+ * {[x = global_margin + margin_x_token + (column - 1) * box_token}
+ * But this does not fit perfectly in the [resource/grid.png].
* The 2 following simple switches are efficient, and simple.
**/
View
2  src/colset.opa
@@ -81,7 +81,7 @@ type ColSet.t = int
/**
* Pick a random elt in the set.
- * Returns { none } if the set is empty
+ * Returns [{none}] if the set is empty
**/
random(set : ColSet.t) : option(ColSet.elt) =
rec aux(elt, set, size) =
View
42 src/game.opa
@@ -19,12 +19,14 @@ import tictactopa.{colset,grid}
**/
/**
- * Representation of grid contents
- * Two players, { free } meaning the location is free.
* Letter stands for red and yellow, the classical colors for this game.
**/
-
type Game.player = { R } / { Y }
+
+/**
+ * Representation of grid contents
+ * Two players, [{free}] meaning the location is free.
+**/
type Game.content = Game.player / { free }
/**
@@ -39,14 +41,13 @@ type Game.content = Game.player / { free }
type Game.action = Grid.column
-
/**
* {2 Status}
**/
/**
* The analysis of a grid
- * + winner : the game is over, the player has win, or {none} for exaeco
+ * + winner : the game is over, the player has win, or [{none}] for exaeco
* + in_progress : the game is in progress, the player should play
* + incoherent : an error occured, the content is incoherent
**/
@@ -146,7 +147,7 @@ type Game.state = {
@both @public GameContent = {{
/**
- * { free } < { R } < { Y }
+ * [{free} < {R} < {Y}]
**/
compare(content : Game.content, content2 : Game.content) =
match (content, content2) with
@@ -162,9 +163,9 @@ type Game.state = {
/**
* Returns the negation of the Game.content.
- * The negation of { free } is { free }.
+ * The negation of [{free}] is [{free}].
**/
- neg_player(player) =
+ neg_player(player) : Game.player =
match player : Game.player with
| { R } -> { Y }
| { Y } -> { R }
@@ -189,7 +190,7 @@ type Game.state = {
@both @public GameUtils = {{
- /**
+ /**
* Return the number of content present in the grid
**/
count(grid : Game.grid, content : Game.content) =
@@ -199,8 +200,8 @@ type Game.state = {
/**
* Check that the difference between player content.
- * {Y} is by convention the first to play.
- * #{Y}-1 <= #{R} <= #{Y}
+ * [{Y}] is by convention the first to play.
+ * An invariant is [#{Y}-1 <= #{R} <= #{Y}]
**/
count_check(grid : Game.grid) =
y = count(grid, {Y})
@@ -247,9 +248,9 @@ type Game.state = {
/**
* Status detection:
- * From a non {free} case, follow from a location in a given direction as long as
+ * From a non [{free}] case, follow from a location in a given direction as long as
* the content does not change, or the value exceed goal. In this case, return the
- * corresponding player, else return [none]
+ * corresponding player, else return [{none}]
**/
follow(grid : Game.grid, i, j, direction : Grid.location) : Game.winner =
goal = GameParameters.goal
@@ -331,12 +332,12 @@ type Game.state = {
/**
* Returns the player which need to play.
- * As a convention, { Y } is always the first
+ * As a convention, [{Y}] is always the first
* to play from an empty grid.
*
- * In case of incohrence, this will return {R}
+ * In case of incohrence, this will return [{R}]
**/
- who_plays(grid : Game.grid) =
+ who_plays(grid : Game.grid) : Game.player =
y = GameUtils.count(grid, { Y })
r = GameUtils.count(grid, { R })
if y == r then { Y } else { R }
@@ -350,7 +351,8 @@ type Game.state = {
/**
* Compute possible actions.
* In particular, If and only if the status is not
- * { in_progress }, the set will be empty.
+ * [{ in_progress }], the set will be empty. The status is defined as {!Game.status}
+ * can be returned by {!GameRules.status}
**/
actions(grid : Game.grid) =
columns = Grid.dimensions(grid).columns
@@ -398,7 +400,7 @@ type Game.state = {
@both @public Game = {{
- make() =
+ make() : Game.state =
goal = GameParameters.goal
// Convention: The Yellow are always the first to play
status = { in_progress = GameParameters.first_player } : Game.status
@@ -414,7 +416,7 @@ type Game.state = {
* Preserve current IA level.
* This is also an optimization for imperative implementation. Relax the GC
**/
- reset(game) =
+ reset(game : Game.state) =
status = { in_progress = GameParameters.first_player } : Game.status
content = { free } : Game.content
grid = Grid.clear(game.grid, content)
@@ -427,7 +429,7 @@ type Game.state = {
* We return a game, updating its status.
* This is a precondition of the function.
**/
- play(game : Game.state, action : Game.action) =
+ play(game : Game.state, action : Game.action) : Game.state =
match game.status with
| { in_progress = player } ->
grid = game.grid
View
22 src/grid.opa
@@ -19,11 +19,10 @@ package tictactopa.grid
/**
* Dimensions of the game. 7 columns, 6 lines.
- * Beware, the number of lines should be a multiple of 2 (precondition of the IA)
+ * Beware, the number of lines should be a multiple of 2 (precondition of the IA).
* Actually, the code looks like generic, and size-extensible, but the ClientLayout,
* as well as the image used for drawing the table is not.
* But, we'd like to be able to use this server lib with some other clients.
- * @public
**/
type Grid.dimensions = {
columns : int ;
@@ -36,7 +35,6 @@ type Grid.dimensions = {
* Speeking as coordonates, we index [(column, line)],
* with column and line starting from value [0], and getting
* until [(Grid.dimensions.columns - 1, Grid.dimensions.lines - 1)]
- * @public
**/
type Grid.column = int
@@ -68,7 +66,7 @@ type Grid.t('content) = {
* for i = min to max do
* iter(i);
* done
- * ]}
+ * }
* Note that the [max] value is also iterated.
**/
for(min, max, iter : int -> void) =
@@ -79,6 +77,14 @@ type Grid.t('content) = {
/**
* The first tuple is the bound of [i], the snd of [j],
* and the function is the iteration.
+ * [for((min, max), (min2, max2), iter)] is equivalent to the imperative form
+ * {[
+ * for i = min to max do
+ * for j = min2 to max2 do
+ * iter(i, j);
+ * done
+ * done
+ * }
**/
for2((min, max), (min2, max2), iter : int, int -> void) =
for_i(i) =
@@ -108,7 +114,7 @@ type Grid.t('content) = {
/**
* Creating a new grid form [dimensions] and a default [content].
**/
- make(dimensions : Grid.dimensions, content) : Grid.t =
+ make(dimensions : Grid.dimensions, content : 'content) : Grid.t =
c = dimensions.columns
l = dimensions.lines
line() = LowLevelArray.create(l, content)
@@ -186,7 +192,7 @@ type Grid.t('content) = {
/**
* Fold. Column by column first, and inside, line by line.
**/
- fold(fold, grid : Grid.t, acc) =
+ fold(fold, grid : Grid.t('content), acc : 'acc) =
t = grid.t
fold_line(line, acc) = LowLevelArray.fold(fold, line, acc)
LowLevelArray.fold(fold_line, t, acc)
@@ -196,7 +202,7 @@ type Grid.t('content) = {
* The location itself is not folded.
* The dist if the maximal distance separating 2 neibourghs.
**/
- fold_neibourgh(fold, grid : Grid.t, location : Grid.location, dist : int, acc) =
+ fold_neibourgh(fold, grid : Grid.t('content), location : Grid.location, dist : int, acc : 'acc) =
dimensions = grid.dimensions
columns = dimensions.columns
lines = dimensions.lines
@@ -220,7 +226,7 @@ type Grid.t('content) = {
/**
- *
+ * iter on all locations of the Grid
**/
iterij(grid : Grid.t, iter) =
dimensions = grid.dimensions
View
20 src/ia.opa
@@ -15,7 +15,7 @@ import tictactopa.{colset,grid}
**/
/**
- *
+ * Supported level of the IA.
**/
type IA.parameters = {level : int}
@@ -46,8 +46,11 @@ type IA.state = {
IA_Winning = {{
- bottom = { R = false ; Y = false }
+ bottom = { R = false ; Y = false } : IA.winning_location
+ /**
+ * Reads the field corresponding to the player
+ **/
read(winning : IA.winning_location, player : Game.player) =
match player with
| {R} -> winning.R
@@ -63,12 +66,6 @@ IA_Winning = {{
@private reset(win : IA.winning_grid) =
Grid.clear(win, bottom)
- /**
- * Compute a winning table.
- * The interface is so that we can use an imperative or a persistent
- * implementation for the winning_grid.
- **/
-
// utils. assert: the location is free
@private winning_ij(grid, i, j, player : Game.content) =
grid = Grid.setij(grid, i, j, player)
@@ -82,6 +79,11 @@ IA_Winning = {{
_grid = Grid.setij(grid, i, j, {free})
res
+ /**
+ * Compute a winning table.
+ * The interface is so that we can use an imperative or a persistent
+ * implementation for the winning_grid.
+ **/
compute(grid : Game.grid, win : IA.winning_grid) : IA.winning_grid =
win = reset(win)
iter(i, j) =
@@ -187,7 +189,7 @@ IA_Winning = {{
* Main function
* For simplicity, the IA is state less.
* It bring a lot of flexibility for this simple game.
- * The status of the grid should be { in_progress } or
+ * The status of the grid should be [{ in_progress }] or
* this will raise an error.
* Since this is stateless, we can by using it add an url
* to the application for having a web service to play the tictactoe
View
16 src/main.opa
@@ -1,5 +1,5 @@
/*
- * Tictactopa. (c) MLstate - 2010
+ * Tictactopa. (c) MLstate - 2011
* @author Mathieu Barbin
**/
@@ -20,4 +20,16 @@ resources = @static_include_directory("resources")
/**
* Start the server, using both [urls] and [resources]
*/
-server = Server.make(Resource.add_auto_server(resources, urls))
+server =
+ Server.make(Resource.add_auto_server(resources, urls))
+
+/*
+Server.resource_map :
+ stringmap(resource) ->
+ Parser.general_parser(resource)
+
+Resource.add_auto_server :
+ stringmap(Resource.resource),
+ Parser.general_parser((http_request -> resource)) ->
+ Parser.general_parser((http_request -> resource))
+*/
Please sign in to comment.
Something went wrong with that request. Please try again.