-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmódulos.pd
547 lines (448 loc) · 16.4 KB
/
módulos.pd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
utilizar bepd/builtins
utilizar bepd/x/enum
utilizar bepd/x/sistemaDeArchivos/archivo como Archivo
utilizar bepd/x/sexpr como SExpr
utilizar bepd/x/entorno como Entorno
utilizar ámbito como Ámbito
[DOCUMENTA
@brief{Configuración de la base de datos.}
La configuración determina como y donde se buscan los módulos. Por ejemplo, si
las rutas para buscar son @code{/ruta/1} y @code{/ruta/2} entonces los módulos
serán buscados como @code{/ruta/1/ejemplo.pd} y
@code{/ruta/2/ejemplo.pd}. Similarmente la configuración también controla las
extensiones aceptadas y su prioridad (es posible que una configuración le de
prioridad a la extensión @code{.pd3} por ejemplo, de forma que si
@code{ejemplo.pd} y @code{ejemplo.pd3} exísten en un mismo directorio
@code{ejemplo.pd3} será siempre importado.
DOCUMENTA]
clase ConfiguraciónGlobal
[DOCUMENTA
@brief{Devuelve la configuración predeterminada.}
Si @pd{usarVariablesDeEntorno} es @pd{VERDADERO}, las variables de entorno
son leídas para extraer algunos valores.
Las variables de entorno leídas son (en órden):
@itemlist(
@item{@code{RUTA_PSEUDOD}}
@item{@code{RUTA_PSEUDOD_BEPD}}
@item{@code{RUTA_PSEUDOD_LIBS}}
)
@pd{rutasBásicas} debe ser un @pd{Arreglo} de @pd{Texto}s con las rutas
iniciales. Con este arreglo puedes agregar rutas específicas a la
configuración generada por este método.
DOCUMENTA]
metodo estatico predeterminado: usarVariablesDeEntorno, rutasBásicas
[DOCUMENTA
@brief{Una configuración global vacía.}
Esta configuración no tendrá rutas en las que buscar ni extensiones a
probar.
DOCUMENTA]
metodo estatico vacía
[DOCUMENTA
@brief{Las rutas donde se deberían buscar los módulos.}
Un arreglo de textos que son rutas a directorios en los que los módulos
deberían ser buscados. Este arreglo esta en órden: los primeros valores
deberían ser buscados primero.
Los valores no incluyen una barra @code{/} al final.
DOCUMENTA]
metodo rutasDondeBuscar
[DOCUMENTA
@brief{Las extensiones de archivo a probar.}
Un arreglo de textos con las extensiones de archivo a probar (excluyendo el
@code{.} al inicio). Tal como @pd{rutasDondeBuscar}, el órden del arreglo
indica que extensiones deberían tener prioridad.
DOCUMENTA]
metodo extensionesAProbar
finclase
atributo ConfiguraciónGlobal#rutas, ConfiguraciónGlobal#extensiones
metodo ConfiguraciónGlobal#inicializar: rutas, exts
fijar yo#rutas a rutas
fijar yo#extensiones a exts
finmetodo
metodo ConfiguraciónGlobal#rutasDondeBuscar
devolver yo#rutas
finmetodo
metodo ConfiguraciónGlobal#extensionesAProbar
devolver yo#extensiones
finmetodo
metodo estatico ConfiguraciónGlobal#predeterminado: usarVariablesDeEntorno, rutasBásicas
variable rutas
fijar rutas a Mapear: rutasBásicas, &Identidad
si usarVariablesDeEntorno
necesitas Entorno#SoportaVariablesDeEntorno
procedimiento DesdeVariable: nombre
variable ruta
fijar ruta a Entorno#ObtenerVariableDeEntorno: nombre
si no EsNulo: ruta
rutas#agregarAlFinal: ruta
finsi
finprocedimiento
DesdeVariable: {RUTA_PSEUDOD}
DesdeVariable: {RUTA_PSEUDOD_BEPD}
DesdeVariable: {RUTA_PSEUDOD_LIBS}
finsi
devolver yo#crear:
(Concatenar:
(Arreglo#crearCon: {.}) [ FIXME: Solo funciona en *NIX. ],
rutas,
(Arreglo#crearCon:
{/opt/pseudod/lib/pseudod/v3},
{/opt/pseudod/lib/pseudod/v3/r0})),
(Arreglo#crearCon:
{pd},
{psd},
{pseudo},
{pseudod})
finmetodo
metodo estatico ConfiguraciónGlobal#vacía
devolver yo#crear: Arreglo#vacio, Arreglo#vacio
finmetodo
[DOCUMENTA
@brief{Identifica de manera única a un módulo.}
Contiene la ruta al archivo, el nombre del módulo y su extensión. En conjunto
estos datos identifican de manera única a un módulo incluso si otros con el
mismo nombre existen en el sistema.
Tanto la ruta como el nombre y la extensión son textos.
DOCUMENTA]
clase LlaveDeMódulo
[DOCUMENTA
@brief{Ruta al módulo.}
Indica el directorio principal. No es necesariamente el directorio que
contiene el archivo, ya que si se importa un módulo @code{hola/mundo}
entonces la ruta solo indica donde encontrar @code{hola}.
DOCUMENTA]
metodo ruta
[DOCUMENTA
@brief{Nombre del módulo.}
Es básicamente el nombre con el que se importó.
DOCUMENTA]
metodo nombre
[DOCUMENTA
@brief{Extensión del archivo del módulo.}
DOCUMENTA]
metodo extensión
[DOCUMENTA
@brief{Nombre del archivo del módulo.}
Junta @pd{ruta}, @pd{nombre} y @pd{extensión} (con una barra @code{/} y un
punto @code{.}) para obtener la ruta completa al archivo del módulo.
DOCUMENTA]
metodo nombreCompletoDelArchivo
[DOCUMENTA
@brief{Inicializa la llave con los valores dados.}
DOCUMENTA]
metodo inicializar: ruta, nombre, ext
[DOCUMENTA
@brief{Devuelve una representación de la llave como texto.}
DOCUMENTA]
metodo comoTexto
finclase
atributos LlaveDeMódulo#ruta, LlaveDeMódulo#nombre, LlaveDeMódulo#extensión
metodo LlaveDeMódulo#inicializar: ruta, nombre, ext
fijar yo#ruta a ruta
fijar yo#nombre a nombre
fijar yo#extensión a ext
finmetodo
metodo LlaveDeMódulo#nombreCompletoDelArchivo
devolver {~t/~t.~t}#formatear: yo#ruta, yo#nombre, yo#extensión
finmetodo
metodo LlaveDeMódulo#comoTexto
devolver {(LlaveDeMódulo: ~t)}#formatear: yo#nombreCompletoDelArchivo
finmetodo
[DOCUMENTA
@brief{Busca un módulo por su nombre.}
@pd{conf} debe ser una @pd{ConfiguraciónGlobal}, cada ruta y extensión será
probada buscando un archivo (o secuencia de directorios conteniendo un archivo)
llamado @pd{nombre}, que debe ser el nombre del módulo (como un texto).
Devuelve la llave del módulo si se encontró, o @pd{NULO} si no se encontró el
módulo.
DOCUMENTA]
procedimiento BuscarMódulo: conf, nombre
variables rutaEnc, nombreEnc, extEnc
LlamarConEC: procedimiento: esc
ParaCadaElemento: conf#rutasDondeBuscar, procedimiento: ruta
ParaCadaElemento: conf#extensionesAProbar, procedimiento: ext
si Archivo#Existe: ({~t/~t.~t}#formatear: ruta, nombre, ext)
fijar rutaEnc a ruta
fijar nombreEnc a nombre
fijar extEnc a ext
%esc: NULO
finsi
finprocedimiento
finprocedimiento
finprocedimiento
si (EsNulo: rutaEnc) || (EsNulo: nombreEnc) || (EsNulo: extEnc)
devolver NULO
finsi
devolver LlaveDeMódulo#crear: rutaEnc, nombreEnc, extEnc
finprocedimiento
[DOCUMENTA
@brief{Un módulo.}
Contiene la llave que lo identifica, junto a la lista de nombres que exporta y
el resultado de compilarlo.
DOCUMENTA]
clase Módulo
[DOCUMENTA
@brief{La llave que identifica a este módulo.}
DOCUMENTA]
metodo llave
[DOCUMENTA
@brief{Alias de @pd{llave#ruta}.}
DOCUMENTA]
metodo ruta
[DOCUMENTA
@brief{Alias de @pd{llave#nombre}.}
DOCUMENTA]
metodo nombre
[DOCUMENTA
@brief{Nombres exportados por este módulo.}
Es un @pd{Ámbito#Ámbito}.
DOCUMENTA]
metodo exporta
[DOCUMENTA
@brief{Resultado de compilar el archivo.}
Es un texto, su contenido depende del backend actual.
Véase también @pd{compiladoAbstracto}, una versión no textual de este
atributo.
DOCUMENTA]
metodo compilado
[DOCUMENTA
@brief{Representación no textual del compilado.}
La versión no textual del atributo @pd{compilado}. Mientras que
@pd{compilado} contiene la versión textual lista para ser guardada en un
archivo, este atributo contiene la versión "interna" que el backend utilizó
para generar @pd{compilado}.
DOCUMENTA]
metodo compiladoAbstracto
[DOCUMENTA
@brief{Información de depuración del módulo.}
Es un texto, su contenido también depende del backend actual.
DOCUMENTA]
metodo informaciónDeDepuración
[DOCUMENTA
@brief{Representación simple del módulo como texto.}
DOCUMENTA]
metodo comoTexto
finclase
atributos Módulo#llave, Módulo#exporta, Módulo#compilado,
Módulo#compiladoAbstracto, Módulo#informaciónDeDepuración
metodo Módulo#ruta
devolver yo#llave#ruta
finmetodo
metodo Módulo#nombre
devolver yo#llave#nombre
finmetodo
metodo Módulo#comoTexto
devolver {(Módulo: llave = ~t, exporta = ~t, compilado = ~t, debuginfo = ~t)}#formatear:
yo#llave, yo#exporta, yo#compilado, yo#informaciónDeDepuración
finmetodo
[DOCUMENTA
@brief{La base de datos de módulos.}
Almacena todos los módulos compilados hasta ahora, y administra la
configuración que se debe usar para buscar más módulos.
Aunque es posible distinguir dos módulos con el mismo nombre por sus llaves, la
base de datos requiere que todos los módulos en ella tengan nombres distíntos.
DOCUMENTA]
clase BaseDeDatos
[DOCUMENTA
@brief{Crea una base de datos con una configuración.}
Esta base de datos no contiene ningún módulo, y utilizará la configuración
@pd{conf}.
DOCUMENTA]
metodo estatico conConfiguración: conf
[DOCUMENTA
@brief{Obtiene la configuración que esta base de datos utiliza.}
DOCUMENTA]
metodo configuración
[DOCUMENTA
@brief{Busca un módulo por su llave.}
Si la base de datos no contiene a un módulo con esta llave, devuelve
@pd{NULO}.
DOCUMENTA]
metodo buscarMóduloPorLlave: llaveDeMódulo
[DOCUMENTA
@brief{Busca un módulo por su nombre.}
Si la base de datos no contiene a un módulo con este nombre, devuelve
@pd{NULO}.
DOCUMENTA]
metodo buscarMóduloPorNombre: nombre
[DOCUMENTA
@brief{Agrega un módulo a la base de datos.}
El módulo no debe haber sido agregado antes.
DOCUMENTA]
metodo agregarMódulo: módulo
[DOCUMENTA
@brief{Itera sobre cada módulo.}
Llama a @pd{proc} con cada módulo en la base de datos.
DOCUMENTA]
metodo paraCadaMódulo: proc
[DOCUMENTA
@brief{Serializa la base de datos.}
@pd{puerto} debe ser un puerto de escritura. Guarda toda la base de datos
como una expresión S.
DOCUMENTA]
metodo guardarMódulos: puerto
[DOCUMENTA
@brief{Deserializa la base de datos.}
@pd{puerto} debe ser un puerto de lectura. Lee toda la base de datos desde
una expresión S.
DOCUMENTA]
metodo cargarMódulos: puerto
finclase
atributos BaseDeDatos#módulos, BaseDeDatos#configuración
metodo estatico BaseDeDatos#conConfiguración: conf
devolver yo#crear: conf
finmetodo
metodo BaseDeDatos#inicializar: conf
fijar yo#configuración a conf
fijar yo#módulos a Diccionario#vacío
finmetodo
metodo BaseDeDatos#buscarMóduloPorLlave: llave
devolver yo#buscarMóduloPorNombre: llave#nombre
finmetodo
metodo BaseDeDatos#buscarMóduloPorNombre: nombre
si yo#módulos#contiene: nombre
devolver yo#módulos#en: nombre
sino
devolver NULO
finsi
finmetodo
metodo BaseDeDatos#agregarMódulo: mod
yo#módulos#fijarEn: mod#nombre, mod
finmetodo
metodo BaseDeDatos#paraCadaMódulo: proc
yo#módulos#paraCadaPar: procedimiento: nombre, mod
%proc: mod
finprocedimiento
finmetodo
metodo BaseDeDatos#guardarMódulos: puerto
funcion A: ...X
devolver X
finfuncion
funcion S: T
devolver SExpr#Símbolo#desdeTexto: T
finfuncion
funcion MapearMódulos: proc
variable acc
fijar acc a Arreglo#vacio
yo#módulos#paraCadaValor: procedimiento: mod
acc#agregarAlFinal: (%proc: mod)
finprocedimiento
devolver acc
finfuncion
variable datum
fijar datum a (A:
(S: {base-de-datos}),
(ArregloConFinal:
(S: {modulos}),
(MapearMódulos: funcion: mod
devolver A:
(A: (S: {nombre}), mod#nombre),
(A: (S: {ruta}), mod#ruta),
(A: (S: {extension}), mod#llave#extensión),
(ArregloConFinal:
(S: {exporta}),
(funcion
variable acc
fijar acc a Arreglo#vacio
mod#exporta#paraCadaVariable: funcion: var, dv
acc#agregarAlFinal: (A: var, dv#esAutoejecutable)
finfuncion
devolver acc
finfuncion)#\llamar\),
(A: (S: {compilado}), mod#compilado)
finfuncion)))
SExpr#DesparsearDato: puerto, datum
finmetodo
metodo BaseDeDatos#cargarMódulos: puerto
funcion SExprADiccionario: se, esArreglo
necesitas EsInstancia: se, Arreglo
variable acc
fijar acc a Diccionario#vacío
ParaCadaElemento: se, procedimiento: val
necesitas EsInstancia: val, Arreglo
si %esArreglo: val
acc#fijarEn: (val#en: 0), (PedazoDeArreglo: val, 1, -1)
sino
acc#fijarEn: (val#en: 0), (val#en: 1)
finsi
finprocedimiento
devolver acc
finfuncion
funcion SExprAPropiedades: se, ignorarPrimero
necesitas EsInstancia: se, Arreglo
variable acc
fijar acc a Diccionario#vacío
ParaCadaElementoConÍndice: se, procedimiento: val, i
si ignorarPrimero && (i = 0)
devolver NULO
finsi
necesitas EsInstancia: val, Arreglo
necesitas EsInstancia: (val#en: 0), SExpr#Símbolo
acc#fijarEn: (val#en: 0)#comoTexto, (PedazoDeArreglo: val, 1, -1)
finprocedimiento
devolver acc
finfuncion
funcion S: T
devolver SExpr#Símbolo#desdeTexto: T
finfuncion
variables datum, props, módulos
fijar datum a SExpr#ParsearDato: puerto
necesitas EsInstancia: datum, Arreglo
necesitas (datum#en: 0) = (S: {base-de-datos})
fijar props a SExprAPropiedades: datum, VERDADERO
fijar módulos a props#en: {modulos}
ParaCadaElemento: módulos, procedimiento: mod
variables vals, exporta
fijar vals a SExprADiccionario: mod, funcion: cons
[ Todas las llaves tienen un único valor excepto `exporta`, que es
un arreglo de pares. ]
devolver (cons#en: 0) = (S: {exporta})
finfuncion
si yo#módulos#contiene: (vals#en: (S: {nombre}))
__FallarConMensaje: ({El módulo ~t ya exíste}#formatear: (mod#en: (S: {nombre})))
finsi
fijar exporta a Ámbito#Ámbito#crear
ParaCadaElemento: (vals#en: (S: {exporta})), procedimiento: par
exporta#agregar: (par#en: 0), NULO
si par#en: 1
exporta#marcarComoAutoejecutable: (par#en: 0)
finsi
finprocedimiento
yo#módulos#fijarEn: (vals#en: (S: {nombre})), (clonar Módulo#_crear con
llave: (LlaveDeMódulo#crear: (vals#en: (S: {ruta})), (vals#en: (S: {nombre})), (vals#en: (S: {extension})))
exporta: exporta
compilado: (vals#en: (S: {compilado}))
informaciónDeDepuración: {} [ FIXME: Guarda la información de depuración. ]
finclonar)
finprocedimiento
finmetodo
[DOCUMENTA
@brief{Trata de buscar un módulo en todo el sistema por su nombre.}
Este procedimiento trata de encontrar un módulo, llamando a:
@itemlist(
@item{@pd{compilar} con la llave, si el módulo existe en el sistema pero no esta
en la base de datos.}
@item{@pd{encontrado} con el módulo, si el módulo existe en la base de datos.}
@item{@pd{error} sin argumentos, si el módulo no fue encontrado.}
)
Devuelve el resultado de llamar a alguno de @pd{compilar}, @pd{encontrado} o
@pd{error}.
DOCUMENTA]
procedimiento ResolverMóduloPorNombre: db, nombre, compilar, encontrado, error
variables enc, llave, mod, conf
fijar conf a db#configuración
fijar enc a db#buscarMóduloPorNombre: nombre
si EsNulo: enc
fijar llave a BuscarMódulo: conf, nombre
si EsNulo: llave
devolver %error
finsi
fijar enc a db#buscarMóduloPorLlave: llave
si EsNulo: enc
devolver %compilar: llave
sino
devolver %encontrado: enc
finsi
sino
devolver %encontrado: enc
finsi
finprocedimiento