Subjective-C
Subjective-C is a joke programming language designed by User:Proxxa to be wholly unintuitive and redundant in its features. One such redundancy is the feature of scopes. Subjective-C is strongly-typed, high-level, and object-oriented.
Naming
Contrary to its name, Subjective-C has nothing to do with the C language. In that respect, it has more to do with Java. The name was given intentionally to both mislead one into making this assumption and to be parallel in naming to "Objective-C".
Hello World Example
Before delving into the intricacies of the language, the following Hello World example and the following explanation will describe a simple program in Subjective-C
export-pkg helloworld. Export file as the helloworld package import-pkg stdio. Import standard IO import-pkg immutable. Import immutability unprotected static object HelloWorld imports stdio and immutable accessible-from *? static immutable-value string HELLOCONST accessible-from mainscope is "Hello, World!". Declare a constant value unprotected static impure method mainMethod with array<string> arguments imports stdio uses-scope mainscope accessible-from *? call-method stdo from stdio with HELLOCONST. Call standard output end method. end object.
The export-pkg
keyword describes what package the current file is accessible from. Package names must be lowercase and use only alphanumeric characters. The .
character is used to dedicate the end of the line. All text after this character on the same line is ignored. import-pkg
imports all unprotected, top-level objects from the described package. The stdio
package encloses methods used for standard input/output. The immutable
package allows the use of a decorator that marks a field of value as immutable.
The unprotected
keyword decorates a type, method, or field as unprotected rather than the default of nonpublic. The static
keyword decorates a type, method, or field as bound to its enclosing type rather than an instance of the type. This keyword is required on user-defined types and top-level methods. object
designates a new user-defined type. The next string of space-delimited text is used as the identifier of the type. imports
defines the packages usable within a scope. accessible-from
defines what scopes a type, field, or method can be accessed from. Using an asterisk (*
) is akin to a wildcard; the HelloWorld object is accessible from all scopes. The ?
character signals the opening of a scope which spans multiple lines. It is used whenever the single-line ~
does not suffice.
immutable-value
is a decorator from the immutable
package which marks a field or value as immutable. string
is a type which acts much like a primitive string of text. The characters in these strings are only one byte in length. The is
keyword assigns a value to a field or variable.
method
designates a method associated with a type or instance. The with
both describes the arguments which a method takes in and what arguments a method is called with. uses-scope
defines which scopes can be accessed from within a scope. The call-method
keyword is placed before a method identifier in order to call it. from
designates in which package to look for an identifier. The end
keyword describes the end of a multi-line scope. It must be followed by the type of scope.
Language Features
Dual-Purpose Line Endings
Lines end with periods. They are required after instructions, and all succeeding text on the same line is ignored. Because of this, periods are also used to begin comments.
Packages
Subjective-C uses a packaging system to separate methods and types into containers. Each package in Subjective-C is its own file, and packages are entirely un-hierarchical.
Exporting Packages
When packages are exported, all the top-level, unprotected types, methods, and values are exported under the name declared by the export-pkg
keyword. This keyword must be at the top of the file.
Importing Packages
To be used within a package, other packages must be both imported by the current package and any scopes using it. Packages must be imported at the top of the file, after the export-pkg
statement with the import-pkg
keyword. It must be then imported into a scope with the imports
keyword. Specific identifiers cannot be imported; instead, all identifiers must be imported from a package.
Methods
Calling methods in Subjective-C has a particular syntax. They require a purity keyword, name, and accessible-from
scope on each declaration. Optionally, they can take in arguments with the with
keyword, import packages with the imports
keyword, and specify return values with the gives
keyword. Methods can then be called using the call-method
keyword.
Return Values
Return types are specified on declaration using the gives
keyword. In the function, the return value is given when the end method
sequence is used by adding with <value>
afterward.
pure static method doublesInteger with integer inputInteger accessible-from exampleScope? end method with inputInteger * 2.
Arguments
Arguments are specified using the with
keyword on both declaration and calling.
impure static method mainMethod imports stdio and stdtypes uses-scope exampleScope accessible-from *? integer shouldBeFour is call-method doublesInteger with 2. string stringified is call-method stringifyInteger with shouldBeFour. call-method stdo from stdio with stringified. Should output "4" to stdout. end method. pure static method doublesInteger with integer inputInteger accessible-from exampleScope? end method with inputInteger * 2.
Scopes
Scoping serves to further categorize pieces of the language. The word "scope" can have two meanings when referring to Subjective-C:
- The code within a type, method, or thread.
- A group given to an identifier to limit what scopes can access it. To avoid ambiguity, this will be referred to as a "scope group" in this section.
The accessible-from
keyword designates which scope group(s) this identifier belongs to. The *
wildcard allows an identifier to belong to all scope groups. This is required for all identifiers, and the identifier can be given multiple groups using the and
keyword.
The uses-scope
keyword designates which scope group(s) this scope may access. If the scope does not specify which scope groups it accesses, it will instead only be able to access the *
scope group.
Assertion
Boolean statements can be asserted true with the assertion operator, !
. If the statement preceding the operator is false
or null
, the current thread will end abruptly.
Threads
"Threads" are special methods which run on their own processor threads. Rather than using the method
type, they use the thread
type. Due to their strange behavior, it is best to understand their use with an example.
pure thread myThread accessible-from funScope with string immutable-value x? . Assert the existence of x x!=null! . Do other things… end thread. End the thread normally impure method funMethod uses-scope funScope imports immutable accessible-from *? string immutable-value myImmutableVariable is "A constant!". spawn myThread with myImmutableVariable. end method.
Due to Subjective-C's lack of conditional statements such as if and else, threads which begin with assertions are the recommended way to ensure the validity of a Boolean statement before executing instructions when such a statement would normally be entered into an if statement. This is an intentionally bad design choice.
Purity Keywords
Subjective-C enforces function purity by the use of a keyword placed before the method/thread keyword. The "pure" keyword describes a function as "pure," and the "impure" keyword describes a function as "impure." Pure functions cannot call impure functions or modify the state of the instance which the function is bound to. It should be noted that all functions which make system calls are counted as impure. As such, the entry point of a program is likely to be impure unless the program has no output. This feature is intentionally pointless.
pure static method myPureMethod accessible-from pureMethodScope gives integer? end method with 3. Return the integer 3 . stdio and stdtypes must be imported into the current package for this method impure static method myImpureMethod uses-scope pureMethodScope imports stdio and stdtypes accessible-from *? integer pureMethodOutput is call-method myPureMethod. string stringifiedOutput is call-method stringifyInteger from stdtypes with pureMethodOutput. call-method stdo from stdio with end method.
Subjectivity
Subjective-C is entirely subjective. That is, if a piece of code seems to fit the style of Subjective-C, it most likely is Subjective-C. Because of this, it is impossible to create a compiler or interpreter for Subjective-C. In fact, it is recommended to never create such an implementation due to the number of poor design choices. It is also recommended that anyone who views this page adds a wholly unintuitive feature to this page. For this purpose, try writing an imaginary program in Subjective-C using features and designs of examples already given by this page.
In essence, Subjective-C is in the eye of the beholder. While this page may give examples of Subjective-C, some may see all the given examples as invalid Subjective-C code.