symbol.ts 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import Type from './type'
  7. import Expression from './expression'
  8. export type Argument<T extends Type = Type> = {
  9. type: T,
  10. isOptional: boolean,
  11. isRest: boolean,
  12. defaultValue: T['@type'] | undefined,
  13. description: string | undefined
  14. }
  15. export function Argument<T extends Type>(type: T, params?: { description?: string, defaultValue?: T['@type'], isOptional?: boolean, isRest?: boolean }): Argument<T> {
  16. const { description = void 0, isOptional = false, isRest = false, defaultValue = void 0 } = params || {}
  17. return { type, isOptional, isRest, defaultValue, description };
  18. }
  19. export type Arguments<T extends { [key: string]: any } = {}> =
  20. | Arguments.List<T>
  21. | Arguments.Dictionary<T>
  22. export namespace Arguments {
  23. export const None: Arguments = Dictionary({});
  24. export interface Dictionary<T extends { [key: string]: any } = {}, Traits = {}> {
  25. kind: 'dictionary',
  26. map: { [P in keyof T]: Argument<T[P]> },
  27. '@type': T
  28. }
  29. export type PropTypes<Map extends { [key: string]: Argument<any> }> = { [P in keyof Map]: Map[P]['type']['@type'] }
  30. export function Dictionary<Map extends { [key: string]: Argument<any> }>(map: Map): Arguments<PropTypes<Map>> {
  31. return { kind: 'dictionary', map, '@type': 0 as any };
  32. }
  33. export interface List<T extends { [key: string]: any } = {}, Traits = {}> {
  34. kind: 'list',
  35. type: Type,
  36. nonEmpty: boolean,
  37. '@type': T
  38. }
  39. export function List<T extends Type>(type: T, params?: { nonEmpty?: boolean }): Arguments<{ [key: string]: T['@type'] }> {
  40. const { nonEmpty = false } = params || { }
  41. return { kind: 'list', type, nonEmpty, '@type': 0 as any };
  42. }
  43. }
  44. export type ExpressionArguments<T> = { [P in keyof T]?: Expression } | { [index: number]: Expression }
  45. export interface MSymbol<A extends Arguments = Arguments, T extends Type = Type> {
  46. (args?: ExpressionArguments<A['@type']>): Expression,
  47. info: {
  48. namespace: string,
  49. name: string,
  50. description?: string
  51. },
  52. args: A
  53. type: T,
  54. id: string,
  55. }
  56. export function MSymbol<A extends Arguments, T extends Type>(name: string, args: A, type: T, description?: string) {
  57. const symbol: MSymbol<A, T> = function(args: ExpressionArguments<A['@type']>) {
  58. return Expression.Apply(Expression.Symbol(symbol.id), args as any);
  59. } as any;
  60. symbol.info = { namespace: '', name, description };
  61. symbol.id = '';
  62. symbol.args = args;
  63. symbol.type = type;
  64. return symbol;
  65. }
  66. export function isSymbol(x: any): x is MSymbol {
  67. const s = x as MSymbol;
  68. return typeof s === 'function' && !!s.info && !!s.args && typeof s.info.namespace === 'string' && !!s.type;
  69. }
  70. export type SymbolMap = { [id: string]: MSymbol | undefined }