Created
April 27, 2018 15:52
-
-
Save lorentey/b224a35146b4b700b020cd0abcd81ac2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Hello | |
This sample file contains examples of all kinds of data that can be stored in a pile. | |
All text up to the first line that consists of a #pile version directive is ignored by the parser. | |
Feel free to write anything here. | |
This is how all text piles start: (The "1" is the version number of the file format.) | |
#pile:1 | |
// This is a one-line comment. | |
/* This is a C-style comment. | |
It may span multiple lines. */ | |
// A text pile is a list of values. The comma character (,) is used to separate values on the same line; it is | |
// otherwise optional. Let's see what kinds of values are supported. | |
// The null value is used to represent Swift's nil optionals and Void values. | |
null | |
// Boolean values are either true or false. | |
true | |
false | |
// Integer literals | |
0000001, -2 // Decimal format | |
0x1234, -0x5678 // Hexadecimal format | |
// Floating point literals | |
0.0, 0000001.0, -2.0, 3e3 // Decimal format with optional power-of-ten exponent value. | |
-0x5678.0p0, 0x1.234p-3 // Hexadecimal format with required power-of-two exponent value. | |
nan, -nan // Not a number. NaNs in piles have no payload and their sign isn't preserved. | |
infinity, -infinity // Positive or negative infinity. | |
// Dates are represented in RFC-3339 format (which is a subset of ISO 8601). | |
// This format handles dates where the (Gregorian) year isn't negative and fits into four digits. | |
// | |
// The time zone infomation included in the format is discarded once the date has been parsed. | |
// Pile serializes all dates in the system's current time zone. | |
// | |
// There is one notable deviation from the spec: Pile uses Unix time so leap seconds are merged into | |
// the previous second. E.g. RFC-3339 requires that the leap second at the end of 2016 is represented as | |
// 2016-12-31T23:59:60Z; however Pile rejects that time and uses 2017-01-01T00:00:00Z instead. | |
// (So the last second of 2016 is merged into the first second of 2017.) | |
// This is because Pile uses Apple's Foundation framework whose Date type uses Unix time. | |
2016-12-16T13:23:12.1832Z // Close to half past one on 16th December 2016 (UTC time) | |
2016-12-16T14:23:12.1832+01:00 // This is the same date in Central European Time | |
2001-01-01T00:00:00Z // This is the reference date used for the relative date format below. | |
// There is also an alternative date representation that uses the number of seconds elapsed from | |
// the beginning of 2001. Pile uses this alternative format for dates in the distant past or distant future | |
// which may not fit into the human-readable RFC3339 format above. | |
// (This also uses Unix time so leap seconds aren't counted.) | |
@0 // The same as 2001-01-01T00:00:00Z | |
@503587392.1832 // The same as 2016-12-16T13:23:12.1832Z | |
@1.25596352736e13 // Sometime around year 400 000 AD. Calendrical calculations are a bit fuzzy in this era. | |
@-1.268619e13 // Sometime around year 400 000 BC. Calendrical calculations are a bit fuzzy in this era. | |
// Unicode strings are enclosed in double quotation marks. | |
"" | |
"hello" | |
"Here is a quote: \" and a newline: \n" // Escape sequences | |
"Dogface emoji: \u{1f436}" | |
// Binary data can be represented in hexadecimal or base 64 notation. | |
<> // Empty hexadecimal data. | |
<828a1d> // Bytes 0x82 0x8a and 0x1d. | |
<828A1D> // Uppercase also works. | |
<82 8A 1D> // Spaces may improve readability. | |
<<>> // Empty base 64 data. | |
<<good>> // Bytes 0x82 0x8a and 0x1d in base 64. | |
// Arrays are enclosed in square brackets. | |
[] | |
[1] | |
[1, 2, 3] | |
[ | |
[1, 2] // It is OK to nest arrays. | |
[3, 4] | |
[5] | |
] | |
// Dictionaries are enclosed in braces. Dictionary keys must be strings. | |
{} | |
{"hello":true} | |
{ | |
"a": 42 | |
"b": 23 | |
} | |
// Custom value types are declared with the #value directive. | |
// Here we declare a Point type with two fields "x" and "y" | |
// representing variant 1 of the unique type "tech.vellum.Point". | |
#value Point(x, y) tech.vellum.Point:1 | |
// Here are two points. Value types are always stored along with a full list of fields enclosed in parentheses. | |
// The field labels aren't optional; you must always spell them out. | |
Point(x: 1.0, y: 2.0) | |
Point( | |
x: 42.0 | |
y: -1.0 | |
) | |
// Custom object types (a.k.a classes) are declared with the #object directive. | |
// Objects are reference types whose identity is preserved. | |
// During serialization the second and subsequent occurances of the same object are replaced with a | |
// reference to the first instance. The only limit is that objects may not form cycles; i.e. | |
// the fields of an object may not contain references to itself. | |
// Note that Pile has no concept of inheritance -- each type has an independent representation. | |
// | |
// Here we define a simple Person type. Each person has a distinct identity. | |
#object Person(firstName, lastName, mother) hu.lorentey.Person:1 | |
// Meet John Smith the son of Maggie Taylor: | |
Person#1( // The #1 here defines a reference number that can be used to identify this Person later. | |
firstName: "John" | |
lastName: "Smith" | |
// John's mother is defined inline with reference number 2. | |
mother: Person#2(firstName: "Maggie", lastName: "Taylor", mother: null) | |
) | |
// And here is his brother Bob: | |
Person( // Not all objects need to be labeled with a reference number. | |
firstName: "Bob" | |
lastName: "Smith" | |
mother: Person#2 // Bob's mother is the same person as John's mother | |
) | |
// Remember John? Here he is again. | |
Person#1 | |
// Finally the last kind of custom type is a #node which is like #object except it is | |
// also allowed to form graphs with cycles. (I.e. nodes may contain references to themselves in | |
// their serialized field values.) | |
// This is a distinct kind of type because cycles are a bit trickier to deserialize. | |
// | |
// Here is a type that can be used to represent a simple social graph where people are friends with each other. | |
#node Friend(nickName, friends) hu.lorentey.Friend:1 | |
// Joe is friends with Sophie and Bill. | |
// Sophie is friends with Joe. | |
// Bill is friends with Sophie, and also with himself which is a little weird. Don't be like Bill. | |
Friend#1(nickName: "Joe", friends: [ | |
Friend#2(nickName: "Sophie", friends: [Friend#1]) | |
Friend#3(nickName: "Bill", friends: [Friend#2, Friend#3]) | |
]) | |
// The optional #end directive stops processing. Everything after it is ignored by the pile parser. | |
#end | |
Feel free to write anything here. | |
(If you don't have anything extra to say it is OK to not include an #end directive.) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment