Пространство имен состоит из имени и списка классов
Класс состоит из имени и списка методов
Метод состоит из имени, типа возвращаемого значения и списка аргументов.
Аргумент состоит из типа и имени
Пример программы на этом простом языке:
Вам также нужно определение типа для вашей системы типов, и это фактически единственное место, где тип объединения имеет значение:
type Type = Void | Int | String
Таким образом, тип в вашем языке - это либо int, либо string, либо void, но не может быть ничем (например, null) и не может быть более одного из этих параметров.
Тип пространства имен может быть полностью анонимным, например:
string * (string * (Type * string * (Type * string) list) list) list
Вы можете определить свое примерное пространство имен следующим образом:
"ns", ["cls1", [Void, "m1", []]
"cls2", [Void, "m2", [Int, "i"; String, "j"]]]
На практике вам, вероятно, понадобится возможность помещать пространства имен в другие пространства имен и помещать классы в классы, чтобы вы могли развить код в нечто вроде этого:
type Type =
| Void
| Int
| String
| Class of Map<string, Type> * Map<string, Type * (Type * string) list>
type Namespace =
| Namespace of string * Namespace list * Map<string, Type>
Namespace("ns", [],
Map
[ "cls1", Class(Map[], Map["m1", (Void, [])])
"cls2", Class(Map[], Map["m2", (Void, [Int, "i"; String, "j"])])])
Анонимные типы хороши, если они не будут источником путаницы. Как правило, если у вас есть два или три поля, и они имеют разные типы (например, «метод»), тогда кортеж - это хорошо. Если имеется больше полей или несколько полей одного и того же типа, то пришло время переключиться на тип записи.
Так что в этом случае вы можете ввести тип записи для методов:
type Method =
{ ReturnType: Type
Arguments: (Type * string) list }
and Type =
| Void
| Int
| String
| Class of Map<string, Type> * Map<string, Method>
type Namespace =
| Namespace of string * Namespace list * Map<string, Type>
Namespace("ns", [],
Map
[ "cls1", Class(Map[], Map["m1", { ReturnType = Void; Arguments = [] }])
"cls2", Class(Map[], Map["m2", { ReturnType = Void; Arguments = [Int, "i"; String, "j"] }])])
и, возможно, вспомогательная функция для создания этих записей:
let Method retTy name args =
name, { ReturnType = retTy; Arguments = args }
Namespace("ns", [],
Map
[ "cls1", Class(Map[], Map[Method Void "m1" []])
"cls2", Class(Map[], Map[Method Void "m2" [Int, "i"; String, "j"]])])