2.1: adda/syntax/parser algorithm for postfix operators:
. when checking for existence,
the word (is) could be used in 2 ways:
(is x) checks for existence,
(x is t) checks for x's type = t .
. another idea is having support for
english-style postfix operators:
then you could write (x exists)
and you'd parse this like an infix
except you're not looking for a 2nd arg .
. its syntax for being declared
could be similar to that of other functions:
myPrefix(arg.argType).ReturnType,
(arg.t)myPostfix.ReturnType,
myInfix(arg1,arg2:t).ReturnType .
-- anything with 2 args is an infix operator .
Showing posts with label syntax. Show all posts
Showing posts with label syntax. Show all posts
2013-03-31
2013-02-28
2012-11-17
concurrency both expressed and automated
8.23: adda/co/finding inherent concurrency automatically:
. how can we analyze a program in order to find
what parts of it can be done concurrently?
. at each step there are implicit inputs and outputs
for step#1, do I know its outputs?
for step#2 do I know its inputs?
(also, when step#1 makes calls,
do any of those calls modify any space that might be
needed by anything step#2 calls? ).
. if step#2's inputs don't intersect step#1's outputs,
then you can do both at the same time .
. to know these things, calls have to be
functional so that program space is obvious .
. when calls have multiple parameters,
the order of their evaluation is random;
which should be tantamount to saying
that parameters in the same tuple
can be run concurrently (co-runnable) .
. this also applies to all tuples that are at
the same level of an expression tree:
eg, in h( f(a,b), g(c,d) ), a,b,c,d are co.runnable .
. a low-level way to compare
subprogramming with coprogramming,
is that while any call could be seen as
a new {process, cpu} activation,
in subprogramming, after making a call,
it agrees to stop working until that call is done .
. often we can find that a group of operations
are all handled by the same type mgt, [11.17:
-- in fact, that is the definition of "(operation):
a subprogram that is outputting
the same type that it's inputting -- ]
so even though they are nested
you can send the whle thing in one call,
and, in that case,
the type mgt will know what's co.runnable .
8.23: todo.adda/co/review parasail's design:
. the parasail lang was able to parallelize implicitly a lot .
(see also comments of this page).
adda/co/explicit concurrency control:
. the abstraction to use for explicit concurrency control
is having a particular cpu called like a function:
cpu#n(subprogram, inputs, outputs)
-- the inputs are a copy of everthing sent to it .
-- outputs are addresses to put results in .
. how is go.lang outputting?
when go.lang says go f(x)
they expect f to either call an outputter
or have x be an outputting channel .
. instead of saying cpu#n(...)
just say co f(x, out), or y`= co f(x) .
8.24: adda/co/syntax:
. there are 2 forms of the function co
according to whether co is synchronous or asynch:
# co(f,g,h) -- co with multiple arguments --
expects spawn and wait .
# co f -- co with just one argument --
just launches f asynchronously .
8.31: co.self/dream/adda/co:
. the dream was something about
"(ways of doing backup for concurrency or ...)
"( ... and now that we can do that,
we can do this ...) [dream recall is too fuzzy].
. how can we analyze a program in order to find
what parts of it can be done concurrently?
. at each step there are implicit inputs and outputs
for step#1, do I know its outputs?
for step#2 do I know its inputs?
(also, when step#1 makes calls,
do any of those calls modify any space that might be
needed by anything step#2 calls? ).
. if step#2's inputs don't intersect step#1's outputs,
then you can do both at the same time .
. to know these things, calls have to be
functional so that program space is obvious .
. when calls have multiple parameters,
the order of their evaluation is random;
which should be tantamount to saying
that parameters in the same tuple
can be run concurrently (co-runnable) .
. this also applies to all tuples that are at
the same level of an expression tree:
eg, in h( f(a,b), g(c,d) ), a,b,c,d are co.runnable .
. a low-level way to compare
subprogramming with coprogramming,
is that while any call could be seen as
a new {process, cpu} activation,
in subprogramming, after making a call,
it agrees to stop working until that call is done .
. often we can find that a group of operations
are all handled by the same type mgt, [11.17:
-- in fact, that is the definition of "(operation):
a subprogram that is outputting
the same type that it's inputting -- ]
so even though they are nested
you can send the whle thing in one call,
and, in that case,
the type mgt will know what's co.runnable .
8.23: todo.adda/co/review parasail's design:
. the parasail lang was able to parallelize implicitly a lot .
(see also comments of this page).
adda/co/explicit concurrency control:
. the abstraction to use for explicit concurrency control
is having a particular cpu called like a function:
cpu#n(subprogram, inputs, outputs)
-- the inputs are a copy of everthing sent to it .
-- outputs are addresses to put results in .
. how is go.lang outputting?
when go.lang says go f(x)
they expect f to either call an outputter
or have x be an outputting channel .
. instead of saying cpu#n(...)
just say co f(x, out), or y`= co f(x) .
8.24: adda/co/syntax:
. there are 2 forms of the function co
according to whether co is synchronous or asynch:
# co(f,g,h) -- co with multiple arguments --
expects spawn and wait .
# co f -- co with just one argument --
just launches f asynchronously .
8.31: co.self/dream/adda/co:
. the dream was something about
"(ways of doing backup for concurrency or ...)
"( ... and now that we can do that,
we can do this ...) [dream recall is too fuzzy].
Labels:
adda,
asynchronous,
concurrency,
Parasail,
syntax
allowed characters in identifiers
8.22: adda/lexicon/allowed characters in identifiers:
. if the allowed characters in an identifier
could include the dot,
then there could be confusion in places,
as to whether the dot was declaring a var:
eg, what if you have the name x.F.int,
and then -- forgetting you did that --
decided later to define F.type ?
. now x.F is ambiguous:
are you declaring x to be F.type?
or are you referring to x.F.int ?
. therefore, the allowed identifiers are
first character is a letter
or the character (_);
and, subsequent characters are alphanums
or the characters (') (_) (-);
anthing else gets put in a box:
eg, [x.F].int; .
. if the allowed characters in an identifier
could include the dot,
then there could be confusion in places,
as to whether the dot was declaring a var:
eg, what if you have the name x.F.int,
and then -- forgetting you did that --
decided later to define F.type ?
. now x.F is ambiguous:
are you declaring x to be F.type?
or are you referring to x.F.int ?
. therefore, the allowed identifiers are
first character is a letter
or the character (_);
and, subsequent characters are alphanums
or the characters (') (_) (-);
anthing else gets put in a box:
eg, [x.F].int; .
class var's declaration syntax
adda/type/class var's declaration syntax:
8.21:
. how does the class var get declared?
how about just like it's called?
. if it's for the instance then we're
writing definitions for self implicitely,
but if there's a class var,
we write as if the var's name is "(type) ...
8.22:
. just as self's public vars are given as
just one tuple definition,
so too the public class vars are like so:
.< ... , type.(x.t), ... > -- a single public class var;
.< ..., .( x,y: t), ... > -- multiple public ivars;
. we could have also written that as:
.< ..., self.( x,y: t), ... >
. parentheses are required in a tuple syntax
even for the singleton? sure:
why have special cases confusing the reader?
in all cases of dotted naming, we are using a tuple,
which in all cases is represented by a parenthetical .
. how does this seem consistent
when generally x = (x) elsewhere?
it's consistent with other typedef syntax;
eg, in f().t the parentheses are required
in order to tell us that this is a function;
ie, any time we see f, we'll be expecting that
any next non-terminal found after f,
will be f's argument;
conversely, without the explicit paren's,
we'd expect f was not accepting args .
8.21:
. how does the class var get declared?
how about just like it's called?
. if it's for the instance then we're
writing definitions for self implicitely,
but if there's a class var,
we write as if the var's name is "(type) ...
8.22:
. just as self's public vars are given as
just one tuple definition,
so too the public class vars are like so:
.< ... , type.(x.t), ... > -- a single public class var;
.< ..., .( x,y: t), ... > -- multiple public ivars;
. we could have also written that as:
.< ..., self.( x,y: t), ... >
. parentheses are required in a tuple syntax
even for the singleton? sure:
why have special cases confusing the reader?
in all cases of dotted naming, we are using a tuple,
which in all cases is represented by a parenthetical .
. how does this seem consistent
when generally x = (x) elsewhere?
it's consistent with other typedef syntax;
eg, in f().t the parentheses are required
in order to tell us that this is a function;
ie, any time we see f, we'll be expecting that
any next non-terminal found after f,
will be f's argument;
conversely, without the explicit paren's,
we'd expect f was not accepting args .
arrays are records are tuples
8.19: adda/dstr/array and record syntax as modes of access:
if ( x.y ) and ( x#y ) are both valid
regardless of whether x is defined as an array or record;
this ignores an idiom where
arrays represent lists of items,
while records represent items with named parts;
. well, my way lets you do it both ways,
but it should be admitted that the writer's freedom
is inevitably the reader's headache .
adda/dstr/array vs record precedence:
. if you have x#y.z
does it mean x#(y.z) or x#(y).z ?
my first impression is that y.z is the tightest binding;
ie, it means x#(y.z);
also, (x#(y) = x#y) only when y is an atom,
and you could argue that y.z is not an atom:
it's a sort of address-addition operation; [11.16:
but, of course, that would be a stretch!
it's more intuitively seen as a style of atom naming .
. finally, consider how functions and arrays
should be similar;
( f x.y ) should be seen as a variant of
( a# x.y ); therefore, the parsing is ( a#(x.y) ). ]
. x.y#z is unambiguous: x has component y,
which is an array taking parameter z;
ie, it's parsed as ( (x.y)#z ).
8.20: adda/dstr/arrays are a species of record.type:
. an array is generating a list of component names,
and then declaring them all to be the same type .
. records are a generalization of this,
where a generated list of components
can have a variety of types .
. in fact, fully-oop arrays are actually records;
because, they often have a variety of types .
. arrays are parameterized types,
and records can be parameterized too
. here's a syntax for allowing a record
to describe parts of itself the way arrays do:
reca(n.int).type: ( a.t1, b.t2, #(0..n).t3 );
x.reca(3)
-- now x = (a:..., b:..., 0:..., 1:..., 2:..., 3:... ).
if ( x.y ) and ( x#y ) are both valid
regardless of whether x is defined as an array or record;
this ignores an idiom where
arrays represent lists of items,
while records represent items with named parts;
. well, my way lets you do it both ways,
but it should be admitted that the writer's freedom
is inevitably the reader's headache .
adda/dstr/array vs record precedence:
. if you have x#y.z
does it mean x#(y.z) or x#(y).z ?
my first impression is that y.z is the tightest binding;
ie, it means x#(y.z);
also, (x#(y) = x#y) only when y is an atom,
and you could argue that y.z is not an atom:
it's a sort of address-addition operation; [11.16:
but, of course, that would be a stretch!
it's more intuitively seen as a style of atom naming .
. finally, consider how functions and arrays
should be similar;
( f x.y ) should be seen as a variant of
( a# x.y ); therefore, the parsing is ( a#(x.y) ). ]
. x.y#z is unambiguous: x has component y,
which is an array taking parameter z;
ie, it's parsed as ( (x.y)#z ).
8.20: adda/dstr/arrays are a species of record.type:
. an array is generating a list of component names,
and then declaring them all to be the same type .
. records are a generalization of this,
where a generated list of components
can have a variety of types .
. in fact, fully-oop arrays are actually records;
because, they often have a variety of types .
. arrays are parameterized types,
and records can be parameterized too
. here's a syntax for allowing a record
to describe parts of itself the way arrays do:
reca(n.int).type: ( a.t1, b.t2, #(0..n).t3 );
x.reca(3)
-- now x = (a:..., b:..., 0:..., 1:..., 2:..., 3:... ).
2012-11-16
benefits of unique context operator
8.19: adda/lexicon/benefits of unique context operator:
[8.20: intro
. in 2012.4, this "(::) was presented as a context operator
but it didn't give a specific reason:
it's name`space limiting:
if you have the syntax ( type`attribute ),
along with ( type`method ),
then the type authors are limited in
what they can name their methods
because it could clash with type attributes; [8.20:
eg, for enums there is an attribute named first;
eg, for bible.type: {last, first},
bible`first = last; -- this type's first value is "(last);
but if the context operation uses the same symbol,
then ( bible`first ) could mean either
the first value of the bible enumeration,
or the bible value named "(first).
. by having a separate context operator (eg, ::),
we can say ( bible`first = bible::last ).]
8.19: 11.15 .. 16: review the syntax:
obj.type(select a variant of this type)
-- declares obj to be of this type;
obj`= value -- object initialization;
type::value -- fully-qualified enumeration value;
obj.component -- public ivar;
type::.component -- public ivar's default initial value;
obj#(component expression) -- public ivar;
type::#(expr) -- public ivar's default initial value;
type.component -- public class var;
type#(component expression) -- public class var;
obj`body/local -- private ivars;
type`body/local -- private class vars;
obj`message(...); -- instance message call;
obj`message`body -- instance message's body;
type::`message`body -- instance message's body;
type::`message -- instance message uninstantiated
( practically the same as type::`message`body );
type`attribute -- class message call;
function(obj) -- call to function of instance
(may or may not belong to an obj's type's interface);
type::subprogram -- full-qualified subprogram call;
type::function`body -- access function's body;
type`body/subprogram -- private class subprogram call;
obj`body/subprogram -- private instance subprogram call;
obj(expr) -- obj callable? apply('obj, expr);
function obj -- call with this obj
. notice there are separate namespaces for
{ value and function names
, .components
, `messages }; because,
components are found only after a dot,
and messages only after a backquote;
whereas, the namespace for value
is shared by that for functions;
otherwise, the parser would have problems:
both values and functions start with a name
but only functions expect the next lexel
to be the argument of that function:
# function x -> apply function to x;
# value x -> syntax error
( unless x is a binary operator
or value is numeric and x is a dimension ).
. therefore, for each unqualified name
it must be typed unambiguously as
either a function or a value, not both .
11.15: mis:
"(review the syntax:
but other times don't eval?
and then this:
type`body/local -- private class vars;
?
. the body of the function is within
the body of the type:
type`body/function
and the way to refer to the function uneval'd,
is to ask for the function's body:
type`body/function`body .
. but if the function is also visible from the interface
we could also write:
type::function`body .
11.16: clarification:
"( review the syntax:
both class and instance public vars,
and these are accessed similarly,
being dotted with their respective objects:
obj.component -- public instance var;
type.component -- public class var .
. if you hadn't defined an instance yet,
and still wanted to refer to an instance's component,
that would be done with the type's context operator:
type::.component;
and, since there was no instance involved,
the only meaning it could logically have
is being the component's default initial value .
[8.20: intro
. in 2012.4, this "(::) was presented as a context operator
but it didn't give a specific reason:
"( confusing having syntax"(type`value). even more than confusing,
when (`) already has a specific meaning: (x`f); ). ]
it's name`space limiting:
if you have the syntax ( type`attribute ),
along with ( type`method ),
then the type authors are limited in
what they can name their methods
because it could clash with type attributes; [8.20:
eg, for enums there is an attribute named first;
eg, for bible.type: {last, first},
bible`first = last; -- this type's first value is "(last);
but if the context operation uses the same symbol,
then ( bible`first ) could mean either
the first value of the bible enumeration,
or the bible value named "(first).
. by having a separate context operator (eg, ::),
we can say ( bible`first = bible::last ).]
8.19: 11.15 .. 16: review the syntax:
obj.type(select a variant of this type)
-- declares obj to be of this type;
obj`= value -- object initialization;
type::value -- fully-qualified enumeration value;
obj.component -- public ivar;
type::.component -- public ivar's default initial value;
obj#(component expression) -- public ivar;
type::#(expr) -- public ivar's default initial value;
type.component -- public class var;
type#(component expression) -- public class var;
obj`body/local -- private ivars;
type`body/local -- private class vars;
obj`message(...); -- instance message call;
obj`message`body -- instance message's body;
type::`message`body -- instance message's body;
type::`message -- instance message uninstantiated
( practically the same as type::`message`body );
type`attribute -- class message call;
function(obj) -- call to function of instance
(may or may not belong to an obj's type's interface);
type::subprogram -- full-qualified subprogram call;
type::function`body -- access function's body;
type`body/subprogram -- private class subprogram call;
obj`body/subprogram -- private instance subprogram call;
obj(expr) -- obj callable? apply('obj, expr);
function obj -- call with this obj
. notice there are separate namespaces for
{ value and function names
, .components
, `messages }; because,
components are found only after a dot,
and messages only after a backquote;
whereas, the namespace for value
is shared by that for functions;
otherwise, the parser would have problems:
both values and functions start with a name
but only functions expect the next lexel
to be the argument of that function:
# function x -> apply function to x;
# value x -> syntax error
( unless x is a binary operator
or value is numeric and x is a dimension ).
. therefore, for each unqualified name
it must be typed unambiguously as
either a function or a value, not both .
11.15: mis:
"(review the syntax:
type::value -- fully-qualified instance value) . sometimes it is using (type::x) to mean eval x,
type::`message -- access message's body
type::function(...) -- access function's body
obj`body/local -- private ivars;
type`body/local -- private class vars;
type`attribute -- class message call;
...
but other times don't eval?
and then this:
type`body/local -- private class vars;
?
. the body of the function is within
the body of the type:
type`body/function
and the way to refer to the function uneval'd,
is to ask for the function's body:
type`body/function`body .
. but if the function is also visible from the interface
we could also write:
type::function`body .
11.16: clarification:
"( review the syntax:
type.component -- public class var;) . an interface definition has syntax for
obj.component -- public ivar;
type::.component -- public ivar's default initial value
both class and instance public vars,
and these are accessed similarly,
being dotted with their respective objects:
obj.component -- public instance var;
type.component -- public class var .
. if you hadn't defined an instance yet,
and still wanted to refer to an instance's component,
that would be done with the type's context operator:
type::.component;
and, since there was no instance involved,
the only meaning it could logically have
is being the component's default initial value .
2012-11-15
task.type's syntax and semantics
adda/co:
8.16: syntax:
. when an object is given a message,
it is the object's type mgt that applies a method;
and, these type mgr's are tasks (co.programs);
but how do we get the obj's themselves
to be tasks? (ie, running code on a separate thread).
8.16: syntax:
. when an object is given a message,
it is the object's type mgt that applies a method;
and, these type mgr's are tasks (co.programs);
but how do we get the obj's themselves
to be tasks? (ie, running code on a separate thread).
Labels:
adda,
asynchronous,
concurrency,
multitasking,
Promise,
syntax,
type
2012-11-11
read-only and write-only params
8.14: adda/cstr/function/syntax/read-only and write-only params:
if a parameter gets a pointer, (eg, /.int)
then it can be modifying both the pointer and the int,
so, shouldn't we have a syntax for expressing
what the algorithm intends to do with both?
. so, we still need a syntax for what is read-only .
. if a parameter expects a read-only,
then we can give it a modifiable
while expecting that it won't modify it .
. how about syntax for write-only?
maybe we should use (.typemark^) for that?
[11.11:
. the latest idea obviates a read-only syntax:
(inout param's)`f(x) -- in that example,
the x param is in-mode only (read-only)
that includes both the pointer and its target .
. notice that if the input is shared by any co.programs,
then we need to lock it as read-only or copy it,
unless we expect it to rely on the interactive value .]
if a parameter gets a pointer, (eg, /.int)
then it can be modifying both the pointer and the int,
so, shouldn't we have a syntax for expressing
what the algorithm intends to do with both?
. so, we still need a syntax for what is read-only .
. if a parameter expects a read-only,
then we can give it a modifiable
while expecting that it won't modify it .
. how about syntax for write-only?
maybe we should use (.typemark^) for that?
[11.11:
. the latest idea obviates a read-only syntax:
(inout param's)`f(x) -- in that example,
the x param is in-mode only (read-only)
that includes both the pointer and its target .
. notice that if the input is shared by any co.programs,
then we need to lock it as read-only or copy it,
unless we expect it to rely on the interactive value .]
Labels:
adda,
cstr,
functional,
multitasking,
param's,
rom,
syntax,
wo
2012-08-26
dialogging exceptions
7.28: adda/cstr/dialogging exceptions/
syntax and fleshing out semantics:
. in adda, dialogging exceptions are
the kind of exceptions which are not call-killing:
they simply give the caller a chance to
fix things in the event of a missing resource:
eg, if a service finds a parameter missing
such as when a file is found to be unreachable,
it will give the caller's file-missing handler
a chance to assign a new file url to an address .
[7.29:
. dialogging exceptions are basically like
implicit parameters that accept a procedure for
what to do in the case of an exceptional situation;
ie, in the usual exception,
the service is quitting and that kills
the whole block that called that service;
so control jumps to the block's exception handlers;
whereas, in the case of dialogging exceptions,
the service is not quitting;
it merely calls an exception handler .]
. for dialogging exceptions,
the handler is expected to return a resource;
so we need syntax for an exception's
returning a value;
it's like a signal but you need a
pointer or inout param because
it's not just reading but writing to the param .
. what if the handler can't help?
if the param is a pointer
it can return nil to indicate failure
indicating the handler is of no help,
so the service then knows to
clean up and throw a returning exception
or give some other indication of failure .
[8.8:
. it's just like a dialog is to the user;
and in that situation,
the user can either find the resourse
and ok the dialog, or cancel it .
. for our example, the service declares:
FileNotFound( f/.filename ).dialog;
-- notice the arg is a pointer type;
and then the handler responds like this:
# a return would be ( f/`= $the/find.txt; );
-- the "(/) is dereferencing the pointer;
and, the target is assigned a literal filename .
# a cancel would be ( f`= none )
-- the pointer itself is assigned no address .
ipc:
. how are we dealing with
pointers that are sent across processes
(ie, how is an arbitrary pointer being thread safe?);
well, in the case of exceptions there are no surprises;
because, it's by invitation only:
the exception raiser is providing an address
for the caller to put a patch into .
8.9: ok,cancel as dialog-local keywords:
. another idea is that the handler's parameter
needs to be an out-mode not a pointer;
and, to handle the dialog
it assigns to the parameter and calls ok;
if the handler has nothing to return,
then it calls cancel to
allow for the service to clean up,
and then it can either propagate an exception
or make a change in strategy,
and then exit from the enclosing block,
or enter some tagged block; eg,
syntax and fleshing out semantics:
. in adda, dialogging exceptions are
the kind of exceptions which are not call-killing:
they simply give the caller a chance to
fix things in the event of a missing resource:
eg, if a service finds a parameter missing
such as when a file is found to be unreachable,
it will give the caller's file-missing handler
a chance to assign a new file url to an address .
[7.29:
. dialogging exceptions are basically like
implicit parameters that accept a procedure for
what to do in the case of an exceptional situation;
ie, in the usual exception,
the service is quitting and that kills
the whole block that called that service;
so control jumps to the block's exception handlers;
whereas, in the case of dialogging exceptions,
the service is not quitting;
it merely calls an exception handler .]
. for dialogging exceptions,
the handler is expected to return a resource;
so we need syntax for an exception's
returning a value;
it's like a signal but you need a
pointer or inout param because
it's not just reading but writing to the param .
. what if the handler can't help?
if the param is a pointer
it can return nil to indicate failure
indicating the handler is of no help,
so the service then knows to
clean up and throw a returning exception
or give some other indication of failure .
[8.8:
. it's just like a dialog is to the user;
and in that situation,
the user can either find the resourse
and ok the dialog, or cancel it .
. for our example, the service declares:
FileNotFound( f/.filename ).dialog;
-- notice the arg is a pointer type;
and then the handler responds like this:
# a return would be ( f/`= $the/find.txt; );
-- the "(/) is dereferencing the pointer;
and, the target is assigned a literal filename .
# a cancel would be ( f`= none )
-- the pointer itself is assigned no address .
ipc:
. how are we dealing with
pointers that are sent across processes
(ie, how is an arbitrary pointer being thread safe?);
well, in the case of exceptions there are no surprises;
because, it's by invitation only:
the exception raiser is providing an address
for the caller to put a patch into .
8.9: ok,cancel as dialog-local keywords:
. another idea is that the handler's parameter
needs to be an out-mode not a pointer;
and, to handle the dialog
it assigns to the parameter and calls ok;
if the handler has nothing to return,
then it calls cancel to
allow for the service to clean up,
and then it can either propagate an exception
or make a change in strategy,
and then exit from the enclosing block,
or enter some tagged block; eg,
( --. begin a block containing a dialog handler .
...
[service that needs a file](f)
-- call the service that may dialog later .
;
on FileNotFound( out f.filename ).dialog:
( f`= [find a new file];
[file was found] ? ok
else: ( cancel; raise MissingResource )
)-FileNotFound
) --end of block with a dialog handler .]
Labels:
adda,
cstr,
dialogs,
exceptions,
syntax
2012-08-23
mixing strings and numbers
7.17: adda/type/mixing strings and numbers:
. suppose the (+)-opererator can be used for
both addition and concatenation;
if we have to eval (string + number),
then the coercion should be to string,
since every number has a string image,
but not every string can eval to a number;
therefore, we should have it so that
. suppose the (+)-opererator can be used for
both addition and concatenation;
if we have to eval (string + number),
then the coercion should be to string,
since every number has a string image,
but not every string can eval to a number;
therefore, we should have it so that
Labels:
adda,
conversions,
syntax,
type
nested subprogram pathnaming
7.17: adda/syntax/nested namespaces of various impl's:
. what is the path delimiter for nested name spaces,
main/sub or
main.sub?
. notice if a file system were
pre-declared and const,
then pointers are not needed;
so, the path is x.y.z not x/y/z .
8.22:
. nested subprograms need not be const's;
they can be redefined at any time
without having to recompile the superprogram;
but the question is moot; because,
. what is the path delimiter for nested name spaces,
main/sub or
main.sub?
. notice if a file system were
pre-declared and const,
then pointers are not needed;
so, the path is x.y.z not x/y/z .
8.22:
. nested subprograms need not be const's;
they can be redefined at any time
without having to recompile the superprogram;
but the question is moot; because,
folder naming like internet subdomains
7.12: adda/dstr/folder naming like internet subdomains:
. in the naming system for subsystems,
the naming of a folder can have a special meaning
because the folder represents
something like a website;
so, just as the top domains
(.com, .org, .net ...)
indicate a website's role type,
these folder types ( .pkg, .type )
can indicate top level domains in our
network of modules .
[8.21:
. later that system would change so that
(.pkg) was the implicit datatype
of any untyped folder
if it was within adda's path .]
. a module can be divided into several folders
by using subdomains; eg,
given these top-level modules:
( int.num.type
, real.num.type )
we can see that both int and real
belong to the same datatype, num;
so, when importing num.type
we're reaching all the folders named *.num.type .
8.8: on the other hand:
. in the naming system for subsystems,
the naming of a folder can have a special meaning
because the folder represents
something like a website;
so, just as the top domains
(.com, .org, .net ...)
indicate a website's role type,
these folder types ( .pkg, .type )
can indicate top level domains in our
network of modules .
[8.21:
. later that system would change so that
(.pkg) was the implicit datatype
of any untyped folder
if it was within adda's path .]
. a module can be divided into several folders
by using subdomains; eg,
given these top-level modules:
( int.num.type
, real.num.type )
we can see that both int and real
belong to the same datatype, num;
so, when importing num.type
we're reaching all the folders named *.num.type .
8.8: on the other hand:
atoms equivalent to tuple singletons
7.7: adda/syntax/atoms equivalent to tuple singletons:
. does a function's arg need a parenthetical?
ie, can we say( f x ), instead of( f(x) )?
if (f x) can be the same as f(x),
then all atoms (such as x)
can be seen as singleton tuples (ie, x=(x) );
so, then there's no need for adda to copy
Python's singleton tuple syntax: ( (x,) ).
. does a function's arg need a parenthetical?
ie, can we say( f x ), instead of( f(x) )?
if (f x) can be the same as f(x),
then all atoms (such as x)
can be seen as singleton tuples (ie, x=(x) );
so, then there's no need for adda to copy
Python's singleton tuple syntax: ( (x,) ).
2012-08-01
(x as type) conversion syntax
3.23: adda/type/syntax/conversion:
. adda conversions should be like python:
val(type);
because try doing it the other way:
type(val):
if the type needs param's,
then it's not obvious whether this is a param'd type
or a type converting a value .
3.14: adda/syntax/conversions look like dimensions:
. in some situations, we may need to
specify the literal's datatype
with a conversion syntax;
conversion should work like dimensions,
as factors: a value is followed by its dimension .
[8.1:
. I'm wondering if that starts to look messy
for general expressions vs literals ...
we'll have a full expression
and then be expecting either a
terminator or a binary operator,
so then finding a typemark means a
conversion of the previous subexpression
(an atom, or a parenthetical).
. does ( f(x) type ) apply to f or x?
. maybe just as there is (x: type)
there could be (x:: type -- conversion)?
but that is counter to most popular uses of [::].
. ada may have had the best idea:
typemark( ... ) would tell you
that typemark was converting (...) .
. a compromise might be ( x(typemark) )
but that could be confused with
function application
-- and the same applies to ada's syntax
since we may want a conversion by
a parameterized type:
typemark(arg)(thing to convert)
-- lots for a reader to remember .
. the keyword "(as) would be memorable:
x as typemark
-- although people coming from Visual Basic
might be confused .
. using english is literally too wordy,
but conversions are mostly automatic,
and shouldn't be seen too often .]
3.23: adda/type/syntax/context specification:
. perhaps the best syntax for specifying a value's type
(in contrast to converting a value to some type)
is to use the possessive syntax:
type`x,
where x can be any symbol defined by the type,
or be an parenthetical expression that is
returning a value of that type .
. adda conversions should be like python:
val(type);
because try doing it the other way:
type(val):
if the type needs param's,
then it's not obvious whether this is a param'd type
or a type converting a value .
3.14: adda/syntax/conversions look like dimensions:
. in some situations, we may need to
specify the literal's datatype
with a conversion syntax;
conversion should work like dimensions,
as factors: a value is followed by its dimension .
[8.1:
. I'm wondering if that starts to look messy
for general expressions vs literals ...
we'll have a full expression
and then be expecting either a
terminator or a binary operator,
so then finding a typemark means a
conversion of the previous subexpression
(an atom, or a parenthetical).
. does ( f(x) type ) apply to f or x?
. maybe just as there is (x: type)
there could be (x:: type -- conversion)?
but that is counter to most popular uses of [::].
. ada may have had the best idea:
typemark( ... ) would tell you
that typemark was converting (...) .
. a compromise might be ( x(typemark) )
but that could be confused with
function application
-- and the same applies to ada's syntax
since we may want a conversion by
a parameterized type:
typemark(arg)(thing to convert)
-- lots for a reader to remember .
. the keyword "(as) would be memorable:
x as typemark
-- although people coming from Visual Basic
might be confused .
. using english is literally too wordy,
but conversions are mostly automatic,
and shouldn't be seen too often .]
3.23: adda/type/syntax/context specification:
. perhaps the best syntax for specifying a value's type
(in contrast to converting a value to some type)
is to use the possessive syntax:
type`x,
where x can be any symbol defined by the type,
or be an parenthetical expression that is
returning a value of that type .
Labels:
adda,
conversions,
syntax
generic parser
2.23: adda/translate/generic parser:
. if there is a generic parser,
then it has to record spaces(n) and new lines,
because the meaning of symbol sequences
will often depend on whether a space
is separating them .
. this may not help me anyway since my interpretation
can depend on whether a name is a type id or not?
. one thing that does simplify things
is a parser that does find and tree
the enclosures and delimiters
-- {} () [] , ; : . --
along with some other un-redefinables .
. it also supports implicit enclosures
(the use of indentation to indicate a grouping)
so it needs to translate ( newline & (some spaces) )
into the beginning or continuation of an enclosure;
and, there needs to be a parameter for
what the currently expected indenting level is .
. if it can find (symbol.type) as being a type def,
then it can also find ( .symbol ) as being a type; [2.29:
but, types shouldn't require a preceding dot .]
. strings of alphanum's that start with alphabet
are always names .
. enclosures include set generators .
. if there is a generic parser,
then it has to record spaces(n) and new lines,
because the meaning of symbol sequences
will often depend on whether a space
is separating them .
. this may not help me anyway since my interpretation
can depend on whether a name is a type id or not?
. one thing that does simplify things
is a parser that does find and tree
the enclosures and delimiters
-- {} () [] , ; : . --
along with some other un-redefinables .
. it also supports implicit enclosures
(the use of indentation to indicate a grouping)
so it needs to translate ( newline & (some spaces) )
into the beginning or continuation of an enclosure;
and, there needs to be a parameter for
what the currently expected indenting level is .
. if it can find (symbol.type) as being a type def,
then it can also find ( .symbol ) as being a type; [2.29:
but, types shouldn't require a preceding dot .]
. strings of alphanum's that start with alphabet
are always names .
. enclosures include set generators .
Labels:
adda,
parse,
syntax,
translation
2012-07-03
tuple literals
6.21: adda/syntax/use of colons to delimit tuple components:
. I wonder if could use python's colon syntax for numeric typing
and still be able to use colons in the usual way
if I am omitting the space: eg, label: t:u:p:l:e .
. this use of omitted space has its precedent in (-),
where minus looks like this: x -y,
while x-y is single name .
if omitting to express default
my way needs something like *:*
because in python the full syntax is [:]
but I have other plans for [],
seq#*:* = python's seq[:]
[:] is a symbol spelled with a colon .
6.29: adda/subparameter delimiters:
. the python string parameters ( start, stop, step )
are delimited by (:) .
. they are like sub parameters,
where instead of a, (1,2,3), c
you can use subparameters to avoid overusing parentheticals:
a, 1:2:3, c .
. the python syntax comes from prior use of (:) to express ranges
-- I first saw this syntax in spreadsheet formulae .
. I wonder if could use python's colon syntax for numeric typing
and still be able to use colons in the usual way
if I am omitting the space: eg, label: t:u:p:l:e .
. this use of omitted space has its precedent in (-),
where minus looks like this: x -y,
while x-y is single name .
if omitting to express default
my way needs something like *:*
because in python the full syntax is [:]
but I have other plans for [],
seq#*:* = python's seq[:]
[:] is a symbol spelled with a colon .
6.29: adda/subparameter delimiters:
. the python string parameters ( start, stop, step )
are delimited by (:) .
. they are like sub parameters,
where instead of a, (1,2,3), c
you can use subparameters to avoid overusing parentheticals:
a, 1:2:3, c .
. the python syntax comes from prior use of (:) to express ranges
-- I first saw this syntax in spreadsheet formulae .
2012-05-31
numeric literals
5.12: adda/syntax/value literals:
. since numeric literals from an arbitrary base
will be using the usual symbols,
we could declare them to be a numeric sub type:
11.B = 2*1+1,
11.B8= 8*1+1,
11.H = 16*1+1 .
. however, that doesn't work because then we are
reserving that symbol for the number literals;
what we need is a way to say BEEF.someType,
and still be able to say BEEF(base16)
in the same context .
. I had previously noted that
[@] 5.10: mis.adda/type/number's base like a dimension?
math's traditional way for expressing base
is with a subscript, hence BEEF#16;
my problem with that was that it
precluded many symbols from being array names;
but, now I see it could still be possible
if we use type names instead of the base's number:
H.type: number; BEEF#H .
but that does get noisy when combining with arrays!
eg, BEEF# BEEF#H = BEEF#48879 .
number sign for value of a type:
. how about a new context notation
for accessing a type's value:
Typemark#valueLiteral,
and then as a special case of that,
numeric bases are types:
eg, H#BEEF
-- not unlike Ada's 16#BEEF#;
but, we can't use 16#BEEF because
it's confusing when used as an array subscript:
eg, A# 16#10 ambiguously means either
A#(16,10) or A#(16#10) (returns an array) .
eg, B#10 for base 2, H#10 for hexadecimals,
O#10 for octals, and T#10 for tetroctals
(base 32 = 4*8 = tetra-oct-al = tetroctal).
review of multi-subscript arrays:
. AT.type: #.int; -- a named array type .
A#.AT; -- an array of array;
means the same as A#.#.int .
. then A is accessed as either A#i#j, or A#(i,j) .
currency sign for value literal spaces:
. another idea is that bases are not really subtypes,
so what we need is a new syntax for value literals:
. it could be like the above except replacing (#) with ($)
-- currency is the sign of value (as in worth);
eg, B$10 = 2, O$10 = 8, and H$10 = 16,
while $10 = still means usa cash;
but, $green can be an abbreviation for
color$green since green is obviously not a number .
. by having the option of using ($) on enumerations,
we can have separate name spaces for them,
so that I can use both the variable green
and the literal color $green in the same context .
TypeId#value vs ValueType$valueLiteral:
. types can be thought of as arrays of values,
so t#x evals x as one of t's values .
. B$10 = the value 10 as parsed by the binary value type .
Color#green works only if green is not redefined;
because in the expression (aType#x),
x can be any expression, not just a literal;
Color$green is always unambiguous;
because the ($) says what follows is
one of a type Color's literals .
. RGB$(0,0,1) -- RGB color model for color literals .
5.10: mis.adda/type/number's base like a dimension?:
. can the notation indicating a number's base
be unified with the dimension system ?
not elegantly, because it confuses a concept:
. the number is a measure,
and the dimension indicates
which property is being measured;
whereas,
in the case of the numeric base indicator,
it indicates how to parse the text .
. we need special syntax for an identifier
to differentiate a typed symbol
from a typed literal value;
because,
the set of literals is indefinitely large from being
defined as a regular expression,
such that there are no identifiers left for symbols .
. numeric literals are from a reserved set of identifiers:
ie, no other symbols than numbers
can start with the digit characters;
but then in bases above 10,
the numeric literal can be confused with a symbol .
. notice too how bases share identifiers:
10 means something different in every base .
. therefore, each literal for non-default base
must have a syntax that says not only the base,
but the fact that this a numeric literal, not a symbol .
. the core system expects ( [, " ) to mean something special,
and all other symbols mean a symbol name .
. a string literal starts with (")
a numeric literal starts with a digit,
an operator symbol starts with non-alphanumeric;
and any other symbol starts with
([),(_), or an alphabetic .
-- literal expressions start with (')
but that's a 2nd meaning of literal because
other literals mean adda should neither parse nor eval,
whereas literal expressions should be parsed .
5.10: adda/type/
defining value literals with regular expressions:
. the general way of handling expressions of literals
is to let the type mgt define it,
so numbers need not be part of the core lang at all,
instead being a module that comes with the core system .
. to generalize the way numeric type define literals,
a type mgt can defines its literals either as
enumerations or as regular expressions .
5.31:
. but if type mgt's are handling all reading of literals,
then constants types aren't known by their assigned values;
because, the value could be a literal,
and no longer implies a particular type .
. one way the above idea could still be useful,
is in talking about compilers that are partial,
and are completed by importing a set of native types,
so then these native types complete the definition of the compiler;
eg, the compiler generator's job is to
analyze all the given native types,
making sure that their literal definitions
are not overlapping .
. it would be a lot simpler to stay classical,
and make some native literals be part of the core language .
5.10: adda/type/review of dimension systems:
. a number can have 3 parts
qty, dimension of qty, and thing being measured:
3 liter water
-- water is a noun measurable by either
volume, mass, moles, or monetary value .
5.12:
. dimensions are used by type physical;
the physical measure type includes a pointer to
a symbol of type physical .
. since numeric literals from an arbitrary base
will be using the usual symbols,
we could declare them to be a numeric sub type:
11.B = 2*1+1,
11.B8= 8*1+1,
11.H = 16*1+1 .
. however, that doesn't work because then we are
reserving that symbol for the number literals;
what we need is a way to say BEEF.someType,
and still be able to say BEEF(base16)
in the same context .
. I had previously noted that
[@] 5.10: mis.adda/type/number's base like a dimension?
math's traditional way for expressing base
is with a subscript, hence BEEF#16;
my problem with that was that it
precluded many symbols from being array names;
but, now I see it could still be possible
if we use type names instead of the base's number:
H.type: number; BEEF#H .
but that does get noisy when combining with arrays!
eg, BEEF# BEEF#H = BEEF#48879 .
number sign for value of a type:
. how about a new context notation
for accessing a type's value:
Typemark#valueLiteral,
and then as a special case of that,
numeric bases are types:
eg, H#BEEF
-- not unlike Ada's 16#BEEF#;
but, we can't use 16#BEEF because
it's confusing when used as an array subscript:
eg, A# 16#10 ambiguously means either
A#(16,10) or A#(16#10) (returns an array) .
eg, B#10 for base 2, H#10 for hexadecimals,
O#10 for octals, and T#10 for tetroctals
(base 32 = 4*8 = tetra-oct-al = tetroctal).
review of multi-subscript arrays:
. AT.type: #.int; -- a named array type .
A#.AT; -- an array of array;
means the same as A#.#.int .
. then A is accessed as either A#i#j, or A#(i,j) .
currency sign for value literal spaces:
. another idea is that bases are not really subtypes,
so what we need is a new syntax for value literals:
. it could be like the above except replacing (#) with ($)
-- currency is the sign of value (as in worth);
eg, B$10 = 2, O$10 = 8, and H$10 = 16,
while $10 = still means usa cash;
but, $green can be an abbreviation for
color$green since green is obviously not a number .
. by having the option of using ($) on enumerations,
we can have separate name spaces for them,
so that I can use both the variable green
and the literal color $green in the same context .
TypeId#value vs ValueType$valueLiteral:
. types can be thought of as arrays of values,
so t#x evals x as one of t's values .
. B$10 = the value 10 as parsed by the binary value type .
Color#green works only if green is not redefined;
because in the expression (aType#x),
x can be any expression, not just a literal;
Color$green is always unambiguous;
because the ($) says what follows is
one of a type Color's literals .
. RGB$(0,0,1) -- RGB color model for color literals .
5.10: mis.adda/type/number's base like a dimension?:
. can the notation indicating a number's base
be unified with the dimension system ?
not elegantly, because it confuses a concept:
. the number is a measure,
and the dimension indicates
which property is being measured;
whereas,
in the case of the numeric base indicator,
it indicates how to parse the text .
. we need special syntax for an identifier
to differentiate a typed symbol
from a typed literal value;
because,
the set of literals is indefinitely large from being
defined as a regular expression,
such that there are no identifiers left for symbols .
. numeric literals are from a reserved set of identifiers:
ie, no other symbols than numbers
can start with the digit characters;
but then in bases above 10,
the numeric literal can be confused with a symbol .
. notice too how bases share identifiers:
10 means something different in every base .
. therefore, each literal for non-default base
must have a syntax that says not only the base,
but the fact that this a numeric literal, not a symbol .
. the core system expects ( [, " ) to mean something special,
and all other symbols mean a symbol name .
. a string literal starts with (")
a numeric literal starts with a digit,
an operator symbol starts with non-alphanumeric;
and any other symbol starts with
([),(_), or an alphabetic .
-- literal expressions start with (')
but that's a 2nd meaning of literal because
other literals mean adda should neither parse nor eval,
whereas literal expressions should be parsed .
5.10: adda/type/
defining value literals with regular expressions:
. the general way of handling expressions of literals
is to let the type mgt define it,
so numbers need not be part of the core lang at all,
instead being a module that comes with the core system .
. to generalize the way numeric type define literals,
a type mgt can defines its literals either as
enumerations or as regular expressions .
5.31:
. but if type mgt's are handling all reading of literals,
then constants types aren't known by their assigned values;
because, the value could be a literal,
and no longer implies a particular type .
. one way the above idea could still be useful,
is in talking about compilers that are partial,
and are completed by importing a set of native types,
so then these native types complete the definition of the compiler;
eg, the compiler generator's job is to
analyze all the given native types,
making sure that their literal definitions
are not overlapping .
. it would be a lot simpler to stay classical,
and make some native literals be part of the core language .
5.10: adda/type/review of dimension systems:
. a number can have 3 parts
qty, dimension of qty, and thing being measured:
3 liter water
-- water is a noun measurable by either
volume, mass, moles, or monetary value .
5.12:
. dimensions are used by type physical;
the physical measure type includes a pointer to
a symbol of type physical .
2012-04-30
typed enclosures
4.29: mis.adda/syntax/typed enclosures:
. adda currently reserves the square brackets
as a way to allow more freedom in identifier spellings:
. the space and all printable characters are allowed
as long as every use of square brackets is paired,
because then the ending bracket is well-defined;
eg, [*thi{ i$ ()ne [eg@l iden]ifier] .
. one way to allow multiple uses for square brackets
is to reserve typed brackets: eg,
[this is a single symbol] --. no typing syntax .
[.M(2,3): ...] --. this is typed as being a 2x3 matrix .
{.R: [a,b)} -- a <= x < b for x in reals .
mis:
. this seems too arbitrary, with no compelling use cases ...
sci:
. however, look at the angle brackets:
while the type is .< ... >
the other use is as a value:
<. ... > or <.type: ...>
and of course the 3rd use is as the less-than,
without any dots nearby .
. adda currently reserves the square brackets
as a way to allow more freedom in identifier spellings:
. the space and all printable characters are allowed
as long as every use of square brackets is paired,
because then the ending bracket is well-defined;
eg, [*thi{ i$ ()ne [eg@l iden]ifier] .
. one way to allow multiple uses for square brackets
is to reserve typed brackets: eg,
[this is a single symbol] --. no typing syntax .
[.M(2,3): ...] --. this is typed as being a 2x3 matrix .
{.R: [a,b)} -- a <= x < b for x in reals .
mis:
. this seems too arbitrary, with no compelling use cases ...
sci:
. however, look at the angle brackets:
while the type is .< ... >
the other use is as a value:
<. ... > or <.type: ...>
and of course the 3rd use is as the less-than,
without any dots nearby .
Subscribe to:
Posts (Atom)