Skip to content

Instantly share code, notes, and snippets.

@lorentey
Created April 27, 2018 15:52
Show Gist options
  • Save lorentey/b224a35146b4b700b020cd0abcd81ac2 to your computer and use it in GitHub Desktop.
Save lorentey/b224a35146b4b700b020cd0abcd81ac2 to your computer and use it in GitHub Desktop.
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