The ideal notation was designed to be easily readable by a programmer who is familiar with Java or C#. Here's quick overview of the ideal-specific features:

Type declarations are introduced with a kind. In addition to class, interface and enum, there are concepts, datatypes and other kinds, which can be read as interfaces. namespace, package, project any module declare types with no instance members. singleton declares a type with exactly one instance.

Supertypes are part of type body declaration and can be prefixed with extends, implements and refines. By convention, the first constructs in type declarations should be supertypes.

For declaring parameterized types, square brackets are used instead of angle brackets. You can use () and [] interchangeably for procedure calls, groupings, and parameterized type declarations; although they must be matched. By convention, [] are used for parameterized types and collection access/initializer.

For declaring variables, a colon is used to distinguish declaration from assignment. Type can usually be inferred, and by default the variable is immutable (final). foo : 68 is equivalent to final int foo = 68 in Java; an error is reported if foo is already defined in scope. To declare a mutable variable, prefix with var, such as var string name : "foo". Assignment is done with =.

For an overview of type flavors that are introduced with keywords readonly, writeonly, mutable, immutable, deeply_immutable, any, pure see the document on the topic.

In constructor invokation, new follows the type declaration, as in hash_set[string].new(). List initializers are expressed as [ foo, bar, baz ]. To create a one-element list, use a trailing comma as in [ foo, ]. (Just [ foo ] is equivalent to ( foo ) and is a grouping construct. )

To check whether a value is an instance of a type, use the is operator, such as if (foo is string) {... The is_not operator performs the check and returns the opposite result. There are two cast operators: .> is a "soft" cast that can never fail (such as converting a type to a supertype), while !> is a "hard" cast that can fail (such as when converting a supertype to subtype.) Casts can be omitted for local variables where they are provably redundant.

In the publication mode, curly braces are omitted in favor of consistent indentation.  Underscores in indentifiers are replaced with spaces, and the dot is replaced with a bullet symbol, so the_list_value.size becomes the list value • size 

That's enough background to start reading ideal code. Good starting points are core library interfaces and base readonly list implementation. The published source is cross-linked, so click on the declarations and identifiers to navigate. For more details, checkout this document.