Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MiniPas

MiniPas es un lenguaje de programación interpretado inspirado en Turbo Pascal V7, diseñado para ser sencillo, educativo y fácil de usar.

⚠️ MiniPas no busca ser compatible con Pascal, Turbo Pascal V7 ó FreePascal: muchas características de Pascal no están soportadas.

Su objetivo principal es permitir experimentar con conceptos básicos de programación estructurada y scripting, ideal para aprendizaje ó pequeños proyectos.

☢️ MiniPas Es un lenguaje experimental y minimalista.

Ejemplo:

// example.mp
program helloworld;
var r: real;

begin
    // comentarios de una linea
    writeln("Hello World in minipas!");
    r := 2.0;
    writeln(); // un espacio en blanco
    writeln("Circunferencia:", 2 * PI * r);// usamos PI
    {   comentarios de
        varias lineas
    }
    writeln("uso de pow:", pow(2,3));
    writeln("uso de sqrt", sqrt(16));
    writeln();
    writeln("platform:", platform());
    writeln("version:", version());
end.

proporciona una salida como la siguiente:

welcome to minipas v0.9.0
cargando archivo: 'example.mp'
Hello, World in minipas!

Circunferencia: 12.566370614359172
uso de pow: 8
uso de sqrt 4

platform: linux
version: 0.9.0 (MiniPas build, unknown, linux) [rustc]

Licencia

Este proyecto está disponible bajo dos licencias distintas.

Puede seleccionar la licencia que mejor se ajuste a sus necesidades, entre las siguientes opciones:

El texto completo de estas licencias, se encuentran en los archivos LICENSE-APACHE y LICENSE-MIT

Instalación (binarios)

Para empezar a utilizar Minipas , descarga el instalador, ejecuta el programa y sigue las instrucciones que aparecen en pantalla.

Gnu/Linux

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/HomeInside/minipas/releases/download/1.9.1/minipas-installer.sh | sh

Windows

powershell -ExecutionPolicy Bypass -c "irm https://github.com/HomeInside/minipas/releases/download/1.9.1/minipas-installer.ps1 | iex"

Instalación manual

Instalación desde el código fuente

La mejor manera de obtener la última y mejor versión de Minipas es instalarla desde el código fuente. Es fácil y solo lleva unos segundos:

Nota:

Si utilizas Windows, fuera de WSL, se recomienda utilizar MSVC, revisa los requisitos para esto, por aquí…

Clona el repo

$ git clone https://github.com/HomeInside/minipas.git

Construye

$ cd minipas
$ cargo build --release

Prueba

$ minipas run examples/hello_world.mp

Realiza las modificaciones que creas convenientes y envíanos un pull request.

Para cualquier duda, comentario, sugerencia ó aporte, dirigete a la seccion de issues.

Antes de abrir un issue nuevo, revisa los ya existentes en busca de una solución (posiblemente ya planteada) para el problema que se te presenta.

Linea de comandos

La herramienta de línea de comandos Minipas, se utiliza para compilar y revisar codigo fuente de archivos .mp. Una vez instalado Minipas, puede ejecutar el comando minipas --help en su terminal para ver los comandos disponibles.

Las siguientes secciones proporcionan información detallada sobre los diferentes comandos disponibles.

  • minipas build Compila un archivo fuente, y genera el AST en formato binario.
  • minipas run Ejecuta un archivo con extensión .mp|.mpc de minipas.
  • minipas emit Genera los Pairs y el AST de un archivo fuente.
  • minipas check Verifica un archivo fuente sin ejecutarlo.

extensiones de archivo

Minipas utiliza las siguientes extensiónes de archivos

  • .mp archivo con código fuente de minipas.
  • .mpc archivo en formato binario (similar a bytecode) de un archivo con código fuente .mp.
  • .mpp archivo en formato JSON, que contiene las Reglas generadas por el parser, de un archivo con código fuente.
  • .mpa archivo en formato JSON, que contiende información del AST generado por el interprete, de un archivo con código fuente.

build

El comando build es utilizado para compilar un archivo con código fuente de minipas.

$ minipas build hello_world.mp

ó de la forma

$ minipas b hello_world.mp

para ambos casos, la salida será algo como:

minipas v.1.9.0
building "hello_world.mp"...
generating AST file (bin): "a.mpc"

OK.

esto creará un archivo con formato binario (similar a bytecode) con la extensíon .mpc.

Nota:

Para más información sobre los archivos .mpc, consulte el comando run.

Importante:

el comando build/b solo acepta archivos con extensión .mp

en caso contrario obtendrá un error como este:

minipas v.1.9.0
minipas error: extensión de archivo de entrada, no valido.
utilice '.mp', para las extensiones de archivo.

try 'minipas --help' for more information

run

El comando run es utilizado para ejecutar un archivo con código fuente de minipas.

las extensiones de archivos permitidas son:

  • .mp archivo con código fuente de minipas.
  • .mpc archivo en formato binario (similar a bytecode) de un archivo con código fuente .mp.
$ minipas run hello_world.mp

ó de la forma

$ minipas r hello_world.mp

para ambos casos, la salida será algo como:

minipas v.1.9.0
Hello World in minipas!

archivos binarios

minipas soporta la ejecución de archivos previamente compilados (comando build)

$ minipas run a.mpc

ó de la forma

$ minipas r a.mpc

para ambos casos, la salida será algo como:

minipas v.1.9.0
Hello World in minipas!

Importante:

el comando run/r solo acepta archivos con extensión .mp ó .mpc.

en caso contrario obtendrá un error como este:

minipas v.1.9.0
minipas error: extensión de archivo no válida.
run: utilice '.mp' ó '.mpc', para extensiones de archivo.

try 'minipas --help' for more information

emit

El comando emit es utilizado para generar archivos que contienen información del parser y del interprete de minipas.

información util para depuración.

$ minipas emit hello_world.mp

ó de la forma

$ minipas e hello_world.mp

para ambos casos, la salida será algo como:

minipas v.1.9.0

generating Pairs file: "hello_world.mpp"
generating AST file (text): "hello_world.mpa"

OK.

esto creará dos archivos con formato JSON

  • archivo .mpp, información del parser

    [
        Pair {
            rule: program,
            span: Span {
                str: "program helloworld;\r\nbegin\r\n    writeln(\"Hello World in minipas!\");\r\nend.\r\n",
                start: 0,
                end: 75,
            },
            inner: [
                Pair {
                    rule: ident,
                    span: Span {
                        str: "helloworld",
                        start: 8,
                        end: 18,
                    },
                    inner: [],
                },
                Pair {
                    rule: semicolon,
                    span: Span {
                        str: ";",
                        start: 18,
                        end: 19,
                    },
                    inner: [],
                },
                Pair {
                    rule: block,
                    span: Span {
                        str: "begin\r\n    writeln(\"Hello World in minipas!\");\r\nend",
                        start: 21,
                        end: 72,
                    },
                    inner: [
                        Pair {
                            rule: stmt,
                            span: Span {
                                str: "writeln(\"Hello World in minipas!\");",
                                start: 32,
                                end: 67,
                            },
                            inner: [
                                Pair {
                                    rule: expr_stmt,
                                    span: Span {
                                        str: "writeln(\"Hello World in minipas!\");",
                                        start: 32,
                                        end: 67,
                                    },
                                    inner: [
                                        Pair {
                                            rule: expr,
                                            span: Span {
                                                str: "writeln(\"Hello World in minipas!\")",
                                                start: 32,
                                                end: 66,
                                            },
                                            inner: [
                                                Pair {
                                                    rule: sum,
                                                    span: Span {
                                                        str: "writeln(\"Hello World in minipas!\")",
                                                        start: 32,
                                                        end: 66,
                                                    },
                                                    inner: [
                                                        Pair {
                                                            rule: product,
                                                            span: Span {
                                                                str: "writeln(\"Hello World in minipas!\")",
                                                                start: 32,
                                                                end: 66,
                                                            },
                                                            inner: [
                                                                Pair {
                                                                    rule: method_chain,
                                                                    span: Span {
                                                                        str: "writeln(\"Hello World in minipas!\")",
                                                                        start: 32,
                                                                        end: 66,
                                                                    },
                                                                    inner: [
                                                                        Pair {
                                                                            rule: factor,
                                                                            span: Span {
                                                                                str: "writeln(\"Hello World in minipas!\")",
                                                                                start: 32,
                                                                                end: 66,
                                                                            },
                                                                            inner: [
                                                                                Pair {
                                                                                    rule: func_call,
                                                                                    span: Span {
                                                                                        str: "writeln(\"Hello World in minipas!\")",
                                                                                        start: 32,
                                                                                        end: 66,
                                                                                    },
                                                                                    inner: [
                                                                                        Pair {
                                                                                            rule: ident,
                                                                                            span: Span {
                                                                                                str: "writeln",
                                                                                                start: 32,
                                                                                                end: 39,
                                                                                            },
                                                                                            inner: [],
                                                                                        },
                                                                                        Pair {
                                                                                            rule: lparen,
                                                                                            span: Span {
                                                                                                str: "(",
                                                                                                start: 39,
                                                                                                end: 40,
                                                                                            },
                                                                                            inner: [],
                                                                                        },
                                                                                        Pair {
                                                                                            rule: expr_list,
                                                                                            span: Span {
                                                                                                str: "\"Hello World in minipas!\"",
                                                                                                start: 40,
                                                                                                end: 65,
                                                                                            },
                                                                                            inner: [
                                                                                                Pair {
                                                                                                    rule: expr_item,
                                                                                                    span: Span {
                                                                                                        str: "\"Hello World in minipas!\"",
                                                                                                        start: 40,
                                                                                                        end: 65,
                                                                                                    },
                                                                                                    inner: [
                                                                                                        Pair {
                                                                                                            rule: expr,
                                                                                                            span: Span {
                                                                                                                str: "\"Hello World in minipas!\"",
                                                                                                                start: 40,
                                                                                                                end: 65,
                                                                                                            },
                                                                                                            inner: [
                                                                                                                Pair {
                                                                                                                    rule: sum,
                                                                                                                    span: Span {
                                                                                                                        str: "\"Hello World in minipas!\"",
                                                                                                                        start: 40,
                                                                                                                        end: 65,
                                                                                                                    },
                                                                                                                    inner: [
                                                                                                                        Pair {
                                                                                                                            rule: product,
                                                                                                                            span: Span {
                                                                                                                                str: "\"Hello World in minipas!\"",
                                                                                                                                start: 40,
                                                                                                                                end: 65,
                                                                                                                            },
                                                                                                                            inner: [
                                                                                                                                Pair {
                                                                                                                                    rule: method_chain,
                                                                                                                                    span: Span {
                                                                                                                                        str: "\"Hello World in minipas!\"",
                                                                                                                                        start: 40,
                                                                                                                                        end: 65,
                                                                                                                                    },
                                                                                                                                    inner: [
                                                                                                                                        Pair {
                                                                                                                                            rule: factor,
                                                                                                                                            span: Span {
                                                                                                                                                str: "\"Hello World in minipas!\"",
                                                                                                                                                start: 40,
                                                                                                                                                end: 65,
                                                                                                                                            },
                                                                                                                                            inner: [
                                                                                                                                                Pair {
                                                                                                                                                    rule: string_literal,
                                                                                                                                                    span: Span {
                                                                                                                                                        str: "\"Hello World in minipas!\"",
                                                                                                                                                        start: 40,
                                                                                                                                                        end: 65,
                                                                                                                                                    },
                                                                                                                                                    inner: [],
                                                                                                                                                },
                                                                                                                                            ],
                                                                                                                                        },
                                                                                                                                    ],
                                                                                                                                },
                                                                                                                            ],
                                                                                                                        },
                                                                                                                    ],
                                                                                                                },
                                                                                                            ],
                                                                                                        },
                                                                                                    ],
                                                                                                },
                                                                                            ],
                                                                                        },
                                                                                        Pair {
                                                                                            rule: rparen,
                                                                                            span: Span {
                                                                                                str: ")",
                                                                                                start: 65,
                                                                                                end: 66,
                                                                                            },
                                                                                            inner: [],
                                                                                        },
                                                                                    ],
                                                                                },
                                                                            ],
                                                                        },
                                                                    ],
                                                                },
                                                            ],
                                                        },
                                                    ],
                                                },
                                            ],
                                        },
                                        Pair {
                                            rule: semicolon,
                                            span: Span {
                                                str: ";",
                                                start: 66,
                                                end: 67,
                                            },
                                            inner: [],
                                        },
                                    ],
                                },
                            ],
                        },
                    ],
                },
                Pair {
                    rule: EOI,
                    span: Span {
                        str: "",
                        start: 75,
                        end: 75,
                    },
                    inner: [],
                },
            ],
        },
    ]
    
  • archivo .mpa, información del AST (interprete)

    [
        Block(
            [
                Expr(
                    Call {
                        name: "writeln",
                        args: [
                            StringLiteral(
                                "Hello World in minipas!",
                            ),
                        ],
                    },
                ),
            ],
        ),
    ]
    

Importante:

El comando emit/e solo acepta archivos con extensión .mp

en caso contrario obtendrá un error como este:

minipas v.1.9.0
minipas error: extensión de archivo de entrada, no valido.
utilice '.mp', para las extensiones de archivo.

try 'minipas --help' for more information

check

Verifica un archivo fuente sin ejecutarlo.

El comando check es utilizado para validar el código fuente, buscando errores de sintaxis.

$ minipas check hello_world.mp

ó de la forma

$ minipas c hello_world.mp

para ambos casos, la salida será algo como:

minipas v.1.9.0
validando pairs...
validando AST...

OK.

Importante:

El comando check/c solo acepta archivos con extensión .mp

en caso contrarió obtendrá un error como este:

minipas v.1.9.0
minipas error: extensión de archivo de entrada, no valido.
utilice '.mp', para las extensiones de archivo.

try 'minipas --help' for more information

hola mundo

program helloworld;
begin
    writeln("Hello World in minipas!");
end.

Guarda este fragmento de código, en un archivo llamado hello_world.mp, en lugar conveniente.

Ahora haz lo siguiente:

$ minipas run hello_world.mp

la salida será algo como:

minipas v.1.9.0
Hello World in minipas!

y eso es todo!

para conocer más acerca de como crear programas en Minipas, consulta Estructura de un programa.

Estructura de un programa

Un programa en minipas, sigue una estructura específica que incluye distintos componentes.

A continuación, se detallan los elementos clave:

Nombre (declaración) del programa

el programa comienza con la palabra clave program, seguido de un nombre cualquiera, este nombre no debe:

  • iniciar con numeros
  • incluir espacios
  • utilizar guión medio (-),

se acepta el guión bajo (_)

program helloworld;

Declaraciones de Variables

Se declaran las variables que se usarán en el programa, especificando su tipo de dato.

var r: real;
var result: real;

Declaraciones de funciones y procedimientos

Incluye la lógica que se ejecutará cuando se llame al procedimiento y/ó función, en caso de que las definas en tu programa.

function calcular(radio:real): real;
begin
    return 2 * PI * radio;
end

Cuerpo del programa

comienza con la palabra clave begin después de la declaración del programa.

begin

Código del Programa

Aquí es donde se implementa la lógica principal, incluyendo operaciones, condiciones, ciclos, etc.

    r := 2.0;
    result := calcular(r);
    writeln("el valor de la Circunferencia es:", result);

Final del Programa

Todo programa en minipas finaliza con la palabra end y un signo de punto (.), al final.

end.

ejemplo completo

program helloworld;

var r: real;
var result: real;

function calcular(radio:real): real;
begin
    return 2 * PI * radio;
end

begin
    r := 2.0;
    result := calcular(r);
    writeln("el valor de la Circunferencia es:", result);
end.

salida

la salida será algo como:

minipas v.1.9.0
el valor de la Circunferencia es: 12.566370614359172

Sintaxis Básica

Ya hemos visto la estructura básica de un programa en minipas, por lo que te resultará fácil comprender otros componentes básicos del lenguaje.

Su objetivo principal es permitir experimentar con conceptos básicos de programación estructurada y scripting, ideal para el aprendizaje ó pequeños proyectos.

Minipas toma muchas caracteristicas y referencias del lenguage Pascal, sin embargo, hay que recalcar algunas cosas:

  • ⚠️ MiniPas no busca ser compatible con Pascal, Turbo Pascal V7 ó FreePascal: muchas características de Pascal no están soportadas.

  • MiniPas es un lenguaje interpretado, inspirado en Turbo Pascal V7, diseñado para ser sencillo, educativo y fácil de usar, la gran mayoría (si no todos…) de los dialectos de Pascal son compilados.

  • Pascal es un lenguaje que no distingue entre mayúsculas y minúsculas (Case Insensitive), lo que significa que puedes escribir tus variables, funciones y procedimientos con cualquiera de las dos. En Minipas no se acepta esto, todas las palabras claves deben escribirse en minúsculas, salvo muy pequeñas excepciones.

  • En minipas, cada sentencia debe terminar en punto y coma (;).

  • ☢️ MiniPas Es un lenguaje experimental y minimalista.

Comentarios

Los comentarios en Minipas pueden ser de la siguiente forma:

  • una sola linea, usando //

    // un comentario antes de todo
    program helloworld;
    begin
        // dentro del bloque principal
        writeln("Hello World in minipas!"); // al lado de una sentencia
    end.
    // un comentario despues del bloque principal
    
  • una sola linea, usando {}

    program helloworld;
    begin
        { dentro del bloque principal }
        writeln("Hello World in minipas!");
    end.
    
  • varias lineas, usando {}

    {
    programming in Minipas
    demo with comments
    Author: John Doe <johndoe@example.com>
    }
    program helloworld;
    begin
        { dentro del bloque principal }
        writeln("Hello World in minipas!");
    end.
    
  • anidados, usando {}

    program helloworld;
    begin
        {
            programming in Minipas
            demo with comments
            Author: John Doe <johndoe@example.com>
            // aqui un comentario de una linea
            // dentro de las llaves
        }
        writeln("Hello World in minipas!");
    end.
    

Tenga en cuenta:

Los comentarios en minipas pueden ir en cualquier parte del programa, o incluso estar anidados y estos serán ignorados por el interprete, aunque se recomienda precaución en estos casos.

Operadores

lista operadores soportandos en minipas.


:=  asignación

Operadores aritmeticos

+    suma                    integer, real, strings
-    diferencia              integer, real
*    producto                integer, real
div  cociente                integer, real
/    cociente                integer, real
mod  residuo                 integer, real
%    residuo                 integer, real

Operadores relacionales

>    mayor qué
<    menor qué
>=   mayor ó igual
<=   menor ó igual
<>   diferente de
=    igualdad

Operadores de asignación (abreviados)

+=   suma y asigna el resultado
-=   resta y asigna el resultado
*=   multiplica y asigna el resultado
/=   divide y asigna el resultado
%=   calcula el residuo de la división y asigna el resultado

Variables

La definición de una variable se coloca en un bloque que comienza con la palabra clave var, seguida de las definiciones de las variables como se muestra a continuación:

  • ejemplo 1:

    // cada variable en una linea
    var nombre: string;
    var edad: integer;
    var mayor_de_edad: boolean;
    
  • ejemplo 2:

    // si son del mismo tipo, pueden ir en una sola sentencia
    var nombre, apellidos: string;
    
  • ejemplo 3:

    // en un bloque de definición
    var
    nombre: string;
    edad: integer;
    mayor_de_edad: boolean;
    

Este tipo de variables definidas despues de la declaracion del programa serán variables globales y estarán disponibles para cualquier función, procedimiento y el bloque principal del programa, durante su ejecución.

Es decir, las variables globales se definen después del encabezado del programa.

Constantes

⚠️ Minipas no admite Constantes

Gramática

La definición de la gramática actual de minipas.

// Minipas grammar.pest 1.8.0
//
WHITESPACE = _{ (" " | "\t" | NEWLINE | comment)+ }
NEWLINE    = _{ "\n" | "\r\n" }

comment_single = { "//" ~ (!NEWLINE ~ ANY)* }
comment_braces = { "{" ~ (!"}" ~ ANY)* ~ "}" }

comment        =  { comment_single | comment_braces }
string_literal = @{
    ("\"" ~ ("\\\"" | "\\\\" | (!"\"" ~ ANY))* ~ "\"")
  | ("'" ~ ("\\'" | "\\\\" | (!"'" ~ ANY))* ~ "'")
}

boolean_literal = { "True" | "False" | "TRUE" | "FALSE" }

// Tokens
keyword_var       = { "var" }
keyword_program   = { "program" }
keyword_integer   = { "integer" }
keyword_real      = { "real" }
keyword_string    = { "string" }
keyword_boolean   = { "boolean" }
keyword_byte      = { "byte" }
keyword_writeln   = { "writeln" }
keyword_if        = { "if" }
keyword_then      = { "then" }
keyword_else      = { "else" }
keyword_const     = { "const" }
keyword_and       = { "and" }
keyword_array     = { "array" }
keyword_for       = { "for" }
keyword_while     = { "while" }
keyword_repeat     = { "repeat" }
keyword_until     = { "until" }
keyword_function  = { "function" }
keyword_procedure = { "procedure" }
keyword_nil       = { "nil" }
// for loop
keyword_to     = { "to" }
keyword_do     = { "do" }
keyword_downto = { "downto" }
// break/continue in loops
keyword_break    = { "break" }
keyword_continue = { "continue" }
break_stmt    = { keyword_break ~ semicolon }
continue_stmt = { keyword_continue ~ semicolon }
// abbreviated operations
assign_add = { "+=" }
assign_sub = { "-=" }
assign_mul = { "*=" }
assign_div = { "/=" }
assign_mod = { "%=" }

ident = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }

number = @{ "-"? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }
real   = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }

assign_op = { ":=" }
add_op    = { "+" }
sub_op    = { "-" }
mul_op    = { "*" }
div_op    = { "/" }
idiv_op   = { "div" }
mod_op    = { "%" | "mod" }
cmp_op    = { ">=" | "<=" | "<>" | ">" | "<" | "=" }

semicolon = { ";" }
comma     = { "," }
colon     = { ":" }
lparen    = { "(" }
rparen    = { ")" }

expr    = { sum ~ (cmp_op ~ sum)? }
sum     = { product ~ ((add_op | sub_op) ~ product)* }

method_chain = { factor ~ ("." ~ ident ~ lparen ~ (expr_list)? ~ rparen)* }
product = { method_chain ~ ((mul_op | div_op | idiv_op |mod_op) ~ method_chain)* }
//product = { factor ~ ((mul_op | div_op | idiv_op |mod_op) ~ factor)* }

//
// llamadas a función/ procedimiento
func_call = { ident ~ lparen ~ (expr_list)? ~ rparen }
factor = { number | string_literal | boolean_literal | func_call | ident | keyword_nil | "(" ~ expr ~ ")" }
// Aquí el `-` delante del número se reconoce como operador unario.
// Esto permite -1 y también expresiones como -(2+3).
//
// factor = { ("-"? ~ number) | string_literal | boolean_literal | func_call | ident | "(" ~ expr ~ ")" }

string    = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
expr_item =  { expr | string_literal }

expr_list = { expr_item ~ (comma ~ expr_item)* }
expr_stmt = { expr ~ semicolon }

// Sentencias
block = { "begin" ~ stmt* ~ "end" }
//stmt  = { comment* ~ (if_stmt | for_stmt | while_stmt | repeat_stmt | block | assignment | expr_stmt | return_stmt) }
stmt  = { comment* ~ (if_stmt | for_stmt | while_stmt | repeat_stmt | break_stmt | continue_stmt | block | assignment | expr_stmt | return_stmt) }

if_stmt = { keyword_if ~ expr ~ keyword_then ~ stmt ~ (keyword_else ~ stmt)? }

var_decl = { ident ~ ("," ~ ident)* ~ ":" ~ (keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte) ~ ";" }

//assignment = { ident ~ assign_op ~ expr ~ semicolon }
assignment = {ident ~ (assign_op | assign_add | assign_sub | assign_mul | assign_div|assign_mod) ~ expr ~ semicolon}

var_section = { ("var" ~ var_decl+)+ }

// procedures
proc_decl = {
    keyword_procedure ~ ident ~ lparen ~ (param_list)? ~ rparen ~ semicolon ~ var_section? ~ block ~ semicolon?
}

// functions
func_decl = {
    keyword_function ~ ident ~ lparen ~ (param_list)? ~ rparen ~ colon ~ (keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte) ~ semicolon ~ (var_section)? ~ block ~ semicolon?
}

// return
return_stmt = { "return" ~ expr ~ semicolon }

// FOR LOOP
for_stmt = {
    keyword_for ~ ident ~ assign_op ~ expr // ~ ("to" | "downto") ~ expr
  ~ (keyword_to | keyword_downto) ~ expr ~ keyword_do ~ stmt
}

// WHILE LOOP
while_stmt   =  {
    keyword_while ~ expr_boolean ~ keyword_do ~ stmt
}
expr_boolean = _{ expr }

// REPEAT LOOP
repeat_stmt = {
    keyword_repeat ~ stmt+ ~ keyword_until ~ expr ~ semicolon
}

param_list   = { param ~ (semicolon ~ param)* }
param        = { ident ~ colon ~ type_keyword }
type_keyword = { keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte }

//
program = {
    SOI ~ comment* ~ "program" ~ ident ~ semicolon ~ var_section? ~ (proc_decl | func_decl)* ~ block ~ "." ~ EOI
}

Tipos de datos

Los tipos de datos indican el significado, las restricciones, los valores posibles, las operaciones, las funciones y el modo de almacenamiento de un valor asociado a el.

Cada valor en minipas es de un determinado tipo de dato, lo que le indica cómo trabajar con ellos al al interprete.

Ten en cuenta que minipas es un lenguaje de tipado fuerte y estático, lo que significa que se debe definir y conocer los tipos de todas las variables antes de la ejecución del programa.

minipas soporta los siguientes tipos de datos:

  • integer números enteros.
  • real números con parte decimal.
  • string cadenas de caracteres.
  • boolean indica solo dos posibles valores, verdadero o falso.
  • byte número entero sin signo que tiene un valor entre 0 y 255.

Valor especial Nulo

minipas usa el valor especial nil (nulo), sin embargo nil, no es un tipo de dato en sí mismo, sino más bien un valor especial que indica la ausencia de un valor ó un valor no asignado.

A tener en cuenta:

En minipas, no puedes asignar un valor nulo (nil) a una variable de la misma manera que en otros lenguajes de programación.

numéricos

Integer

Un entero es un número sin componente fraccionario. Esto incluye todos los números sin parte decimal, tanto positivos como negativos.

Rango de Valores

El rango específico de valores que puede almacenar un integer puede variar dependiendo de la implementación, pero generalmente en Pascal es de -32,768 a 32,767. En minipas, este valor se incrementa ya que se utiliza i64 de Rust, lo que amplía significativamente el valor a usar en una variable.

  • Turbo Pascal v 7 \begin{cases} \text -2^{15} \text{ hasta }\ 2^{15} - 1 \ \end{cases}

  • Minipas \begin{cases} \text -2^{63} \text{ hasta }\ 2^{63} - 1 \ \end{cases}

Ejemplo

program hello_integers;
var
    a,b,c: integer;
begin
    writeln("Hello World in minipas!");
    writeln();
    writeln("el valor de a es:", a);
    writeln("el valor de b es:", b);
    writeln("el valor de c es:", c);
end.

Real

Se refiere a un tipo de dato que se utiliza para representar números que tienen parte decimal. Estos tipos son esenciales para realizar cálculos que requieren precisión con decimales, como operaciones matemáticas complejas, mediciones, y otros casos donde los números enteros no son suficientes.

Rango de Valores

El rango específico de valores que puede almacenar un integer puede variar dependiendo de la implementación, pero generalmente en Pascal es de -32,768 a 32,767. En minipas, este valor se incrementa ya que se utiliza f64 de Rust, lo que amplía significativamente el valor a usar en una variable.

  • Turbo Pascal v 7 \begin{cases} \text 2.9 \times 10^{-39} ;\text{ hasta }; 1.7 \times 10^{38} \ \end{cases}

  • Minipas \begin{cases} \text 1.8 \times 10^{308} \ \end{cases}

Ejemplo

program hello_real;
var
    a,b,c: real;
begin
    writeln("Hello World in minipas!");
    writeln();
    writeln("el valor de a es:", a);
    writeln("el valor de b es:", b);
    writeln("el valor de c es:", c);
end.

Byte

Es un tipo especial de entero que tiene un rango de valores de 0 a 255, por lo que no soporta valores negativos.

Ejemplo

program hello_byte;
var
    edad: byte;
begin
    writeln("Hello World in minipas!");
    writeln();
    edad:= 256; //genera un error, ya que el valor maximo es 255
    writeln("el valor de edad es:", edad);
end.


Nota:

Para una mejor compresión recomendamos leer

strings

Se utilizan para representar cadenas de caracteres, el rango de un tipo de dato string depende de la longitud de la cadena y del uso de memoria.

Las cadenas de caracteres, son en realidad una secuencia de caracteres con una especificación de tamaño opcional. Los caracteres pueden ser numéricos, letras, espacios en blanco, caracteres especiales o una combinación de todos ellos. Extended Pascal proporciona numerosos tipos de objetos de cadena dependiendo del sistema y la implementación. Analizaremos los tipos de cadenas más comunes utilizados en los programas.

En minipas un tipo de dato string es internamente String de Rust, para asignar un valor se puede utilizar indistintamente comillas ("") o apóstrofos (''), aquí recomendamos el uso de comillas.

Ejemplo

program hello_strings;
var
    nombres: string;
begin
    writeln("Hello World in minipas!");
    writeln();
    nombres := "john";
    writeln("el nombres es:", nombres);
end.


Nota:

Para una mejor compresión recomendamos leer

boleanos

Representan valores de verdad. Generalmente, un boleano puede tener solo dos posibles valores.

En Minipas, un valor boleano se representa de la siguiente manera, con la primera letra en Mayúscula:

  • True (verdadero)
  • False (falso)

Recuerda que los valores booleanos son lógicos y no numéricos. Esto lo hace útil para la toma de decisiones en la lógica de programación y control de flujo.

Ejemplo

program hello_booleans;

var
esMayorDeEdad: boolean;

begin
    writeln("esMayorDeEdad al inicio es:", esMayorDeEdad);
    esMayorDeEdad := True;

    if esMayorDeEdad then
        writeln('Es mayor de edad.');
    else
        writeln('No es mayor de edad.');
end.


Nota:

Para una mejor compresión recomendamos leer

arrays

⚠️ Minipas no admite arreglos(Arrays)

Control de flujo

Las estructuras de toma de decisiones requieren que el programador especifique una o más condiciones que el programa debe evaluar o comprobar, junto con una o varias instrucciones que se ejecutarán si la condición se determina como verdadera y, opcionalmente, otras instrucciones que se ejecutarán si la condición se determina como falsa.

A continuación se muestra la forma general de una estructura de toma de decisiones típica.

flowchart TD
    A([ ]) --> B{condición}
    B -- "si la condición se cumple" --> C[código condicional]
    B -- "la condición NO se cumple" --> D(( ))

    C --> D

    %% Estilos
    style A fill:#fff,stroke:#000
    style D fill:#fff,stroke:#000
    style B fill:#000,stroke:#fff,color:#fff
    style C fill:#000,stroke:#fff,color:#fff

    linkStyle 0 stroke:#000,stroke-width:2px
    linkStyle 1 stroke:#000,stroke-width:2px
    linkStyle 2 stroke:#000,stroke-width:2px
    linkStyle 3 stroke:#000,stroke-width:2px

Minipas proporciona los siguientes tipos de sentencias de toma de decisiones:

  • Sentencia if-then: Una sentencia if-then consta de una expresión booleana seguida de una o más sentencias.

  • Sentencia if-then-else: Una sentencia if-then puede ir seguida de una sentencia else opcional, que se ejecuta cuando la expresión booleana es falsa.

  • Sentencias if anidadas: Se puede utilizar una sentencia if o else if dentro de otra sentencia if o else if.

  • sentencia case:

    ⚠️ Minipas no admite case

sentencia if

Sentencia if-then

La instrucción if-then es la forma más simple de instrucción de control, utilizada con frecuencia en la toma de decisiones y para cambiar el flujo de control de la ejecución del programa.

La sintaxis de la instrucción if-then es:

if condición then sentencias;

Donde condición es una condición booleana o relacional y sentencias es una instrucción simple o compuesta. Un ejemplo de una instrucción if-then es:

if a <= 20 then
   c := c+1;

Si la condición de la expresión booleana se evalúa como verdadera, se ejecutará el bloque de código dentro de la instrucción if. Si la expresión booleana se evalúa como falsa, se ejecutará el primer conjunto de código después del final de la instrucción if.

Miremos con un ejemplo completo:

Ejemplo

program ifExample;

var a: integer;

begin
  a:= 10;

  // se puede usar parentesis
  //
  // if (a < 20) then
  //
  if a < 20 then
      writeln("a menor que 20");
end.

salida

la salida será algo como:

minipas v.1.9.0
a menor que 20

Sentencia if-then-else

Una instrucción if-then puede ir seguida de una instrucción else opcional, que se ejecuta cuando la expresión booleana es falsa.

La sintaxis de la instrucción if-then-else es:

if condición then Sentencias1; else Sentencias2;

Donde Sentencias1 y Sentencias2 son sentencias diferentes.

En las sentencias if-then-else, cuando la condición de prueba es verdadera, se ejecuta la sentencia Sentencias1 y se omite Sentencias2, cuando la condición de prueba es falsa, se omite Sentencias1 y se ejecuta la sentencia Sentencias2.


A tener en cuenta:

En Minipas, cada sentencia debe terminar en punto y coma (;).

Ejemplo

program ifElseExample;
var
  a : integer;

begin
  a := 100;
  // se puede usar parentesis
  //
  // if (a < 20) then
  //
  if a < 20 then
      writeln("a es menor que 20");
  else
      writeln("a es mayor, el valor de a es:", a);
end.

salida

la salida será algo como:

minipas v.1.9.0
a es mayor, el valor de a es: 100

Sentencias if-then else if-then

Una instrucción if-then puede ir seguida de una instrucción else if-then-else opcional, lo cual resulta muy útil para comprobar varias condiciones utilizando una única instrucción if-then-else.

Ejemplo

program ifElse_ifElseExample;
var
  a: integer;

begin
  a := 100;

  if a = 10 then
      writeln("el valor de a es: 10");
  else if a = 20 then
      writeln("el valor de a es: 20");
  else if a = 30 then
      writeln("el valor de a es: 30");
  else
      writeln("Ninguno de los valores coincide.");
end.

salida

la salida será algo como:

minipas v.1.9.0
Ninguno de los valores coincide.

Instrucciones simples ó compuestas

Una instrucción simple es una línea de código que realiza una única acción. Estas instrucciones son directas:

if a <= 20 then
   c := c+1; // <- instrucción simple

Una instrucción compuesta es un bloque de código que puede contener cero o más instrucciones simples, ó incluso instrucciones compuestas dentro (anidadas). Se utiliza para agrupar varias acciones bajo un mismo control de flujo.

La sintaxis de una instrucción compuesta incluye begin y end, que delimitan el bloque de instrucciones:

if a <= 20 then begin // <- 'begin' indica el inicio del bloque
   c := c+1;
   writeln("El valor de C es:", c);
end // <- 'end' indica el fin del bloque

A tener en cuenta:

En minipas, cada bloque begin debe terminar con un end, pero este end no debe llevar punto y coma (;) al final.


Los ejemplos anteriores se componen de sentencias simples, ahora veamos un ejemplo utilizando sentencias compuestas:

Ejemplo

program ifStatemensExample;

var a: integer;

begin
  a := 50;

  if a = 10 then begin
      writeln("el valor de a es 10");
      a := a + 1;
      writeln("el valor de a es:", a);
  end
  else if a = 20 then begin
      writeln("el valor de a es 20");
      a := a * 2;
      writeln("el valor de a es:", a);
  end
  else begin
      writeln("el valor de a es diferente de 10 y 20");
      a := a - 1;
      writeln("el valor de a es:", a);
  end
end.

salida

la salida será algo como:

minipas v.1.9.0
el valor de a es diferente de 10 y 20
el valor de a es: 49

A tener en cuenta:

Se recomienda usar un bloque begin/end, cuando se tenga dos ó más instrucciones en un bloque if-then, if-then-else etc…

Sentencias if anidadas

Siempre es legal anidar sentencias if-else, lo que significa que se puede utilizar una sentencia if o else if dentro de otra sentencia if o else if. Minipas permite anidar hasta cualquier nivel, sin embargo, las sentencias anidadas pueden volverse complicadas, así que es importante mantener el código legible y organizado.

La sintaxis de una instrucción if anidada es la siguiente:

if condicion_1 then
   if condicion_2 then sentencias1;
else
   sentencias2;

otro ejemplo:

if condicion_1 then
   if condicion_2 then begin
      sentencias1
      sentencias2
   end
else begin
   if condicion_3 then begin
     if condicion_4 then begin
       sentencias3;
       sentencias4;
     end
   end
end

A tener en cuenta:

Recuerda que las sentencias anidadas pueden volverse complicadas, así que es importante mantener el código legible y organizado.

Ejemplo

program NestedIfElseExample;
var
   a, b: integer;

begin
   a := 100;
   b := 200;

   if a = 100 then
      if b = 200 then
         writeln("el valor de a es 100 y el valor de b es 200");
end.

salida

la salida será algo como:

minipas v.1.9.0
el valor de a es 100 y el valor de b es 200

Uso de if Anidadas en Situaciones Prácticas

Las sentencias if anidadas son útiles, por ejemplo, en situaciones donde deban verificarse múltiples criterios para cumplir con ciertas condiciones lógicas. Esto puede incluir:

  • Validaciones en entradas de usuario.
  • Cálculos que dependen de diferentes rangos.
  • Procesamiento de datos donde ciertos parámetros dependen de otros.

Consideraciones

  • Legibilidad: Las sentencias anidadas pueden volverse complicadas, así que es importante mantener el código legible y organizado. si anidas mucho, considera el uso de bloques begin/end.
  • Indentación: Usar una buena indentación ayuda a visualizar mejor la estructura anidada y la lógica del flujo del programa.
  • Manejo de Errores: Las sentencias anidadas pueden dificultar la identificación de errores, así que es aconsejable descomponer problemas complejos en funciones más manejables cuando sea posible.

funciones

Una función es un grupo de sentencias que juntas realizan una tarea.

Definición de una función

Una declaración de función le indica al interprete el nombre, el tipo de retorno y los parámetros de una función. Una definición de función proporciona el cuerpo real de la función.

Las funciones pueden aceptar (ó no) parámetros (que son variables definidas en la cabecera de la función) y estos parámetros son utilizados para recibir valores al momento de invocar la función.

En Minipas, una función se define utilizando la palabra clave function.

La forma general de una definición de función es la siguiente:

ejemplo de función que acepta argumentos:

function nombre_funcion(param1: tipo1; param2: tipo2; ...): tipo_de_retorno;
// declaraciones locales usando `var`, si aplica

begin // <- el cuerpo de la funcion, comienza con 'begin'
   sentencia1;
   sentencia2;
   ...
   return valor, ó sentencia
end // <- el cuerpo de la funcion, finaliza con 'end'

ejemplo de función que no acepta argumentos:

function nombre_funcion(): tipo_de_retorno;
// declaraciones locales usando `var`, si aplica

begin // <- el cuerpo de la funcion, comienza con 'begin'
   sentencia1;
   sentencia2;
   ...
   return valor, ó sentencia
end // <- el cuerpo de la funcion, finaliza con 'end'

Parámetros: establecen el vínculo entre el programa de llamada y los identificadores de función, y también se denominan parámetros formales. Un parámetro es como un marcador de posición. Cuando se invoca una función, se pasa un valor al parámetro. Este valor se denomina parámetro real o argumento. La lista de parámetros se refiere al tipo, el orden y el número de parámetros de una función. El uso de dichos parámetros formales es opcional. Estos parámetros pueden tener un tipo de dato estándar, un tipo de datos definido por el usuario o un tipo de datos de subrango.

Argumento: por otro lado, es el valor real que se pasa a la función o procedimiento al momento de su invocación. Es el dato que ocupa la posición del parámetro definido en la cabecera.

resumiendo un poco:

  • Parámetros son las variable en la declaración de la función.
  • Argumentos son los valores reales pasado en la llamada, usados en la invocación de la función.

Tipo de retorno: todas las funciones deben devolver un valor, por lo que a todas las funciones se les debe asignar un tipo. El tipo de función es el tipo de datos del valor que devuelve la función. Puede ser un tipo estándar, escalar, definido por el usuario o de subrango, pero no puede ser un tipo estructurado.

Declaraciones locales: las declaraciones locales se refieren a las declaraciones de etiquetas, variables, que se aplican únicamente al cuerpo de la función.

Cuerpo de la función: contiene un conjunto de sentencias que definen lo que hace la función. Siempre debe estar entre las palabras reservadas begin y end. Es la parte de una función donde se realizan todos los cálculos.

Retorno: cada función termina con la palabra reservada return y una valor asociado a un tipo de dato ó una expresión.

Llamar a una función

Al crear una función, se define lo que debe hacer dicha función. Para utilizar una función, hay que llamarla(ó invocarla) para que realice la tarea definida. Cuando un programa llama a una función, el control del programa se transfiere a la función llamada, esta realiza la tarea definida y, cuando se ejecuta su instrucción de retorno (return), devuelve el control del programa, al programa principal.

Llamar/invocar a una función implica:

  • usar el nombre definido para ella
  • enviarle argumentos (si los acepta)
  • esperar (ó no) una respuesta
// si la función recibe argumentos
nombre_funcion(arg1, arg2, ...);
// si la función NO recibe argumentos
nombre_funcion();

veamos un ejemplo

Ejemplo

program test_functions;

// nombre de la función, parametros y tipo de retorno
function sumar(a:integer; b:integer): integer;

// declaraciones locales
var c: integer;

//cuerpo de la función
begin
    writeln("el valor de a es:", a);
    writeln("el valor de b es:", b);
    c := a + b;
    writeln("el valor de c es:", c);
    
    // valor ó sentencia de retorno
    return c;

end // fin de la función

// bloque principal del programa
begin
    writeln();
    writeln("3 + 5 = ", sumar(3, 5)); // <- llamada a la función
    writeln("10 + 20 = ", sumar(10, 20)); // <- llamada a la función
    writeln();
    sumar(2, 9); // <- llamada a la función
    writeln();
end.

salida

la salida será algo como:

minipas v.1.9.0

el valor de a es: 3
el valor de b es: 5
el valor de c es: 8
3 + 5 =  8
el valor de a es: 10
el valor de b es: 20
el valor de c es: 30
10 + 20 =  30

el valor de a es: 2
el valor de b es: 9
el valor de c es: 11

A tener en cuenta:

Recuerda que las funciones (definidas usando function) siempre devuelven un valor.

valor de retorno

Como se especificó anteriormente, las funciones siempre devuelven un valor, asi que podemos “capturar” ese valor en una variable y hacer alguna operación ó simplemente mostralo.

Ejemplo

el mismo ejemplo sin comentarios, y omitiendo mostrar muchos valores por la consola.

program test_functions;
var resultado: integer;

function sumar(a:integer; b:integer): integer;
var c: integer;

begin
    c := a + b;
    return c;
end

begin
    resultado := sumar(2, 9);
    writeln("el resultado de la suma es:", resultado);
end.

salida

la salida será algo como:

minipas v.1.9.0
el resultado de la suma es: 11

Consideraciones

Definición Clara: Asegúrate de que la función tenga un propósito específico y bien definido.

Nombres descriptivos: Usa nombres significativos que reflejen la acción que realiza la función (por ejemplo, sumar).

Número de parámetros y argumentos: Los argumentos deben coincidir en número y tipo con los parámetros definidos en la función.

Limita el número de parámetros para mantener la simplicidad.

Valor de retorno: Especifica el tipo de retorno de la función claramente y asegúrate de que devuelve un valor adecuado.

Documentación: Comenta el código para explicar qué hace la función, sus parámetros y valor de retorno.

Evitando efectos secundarios: Trata de evitar modificar variables globales a menos que sea necesario; esto ayuda a mantener la función predecible.

Pruebas y validaciones: Implementa pruebas para garantizar que la función produzca los resultados esperados con varios datos de entrada.

Considera agregar validaciones de entrada para evitar errores.

Código modular: Divide la lógica del programa en funciones más pequeñas y manejables; esto facilita la lectura y el mantenimiento del código.

Anidamiento: Puedes llamar a otras funciones dentro de una función, pero ten cuidado con la profundidad anidada para no complicar la lógica.

Gestión de errores: Implementa manejo de errores donde sea necesario para evitar fallos inesperados durante la ejecución.

Recursividad: Si usas funciones recursivas, asegúrate de tener una condición de salida clara para evitar bucles infinitos.

procedimientos

Los procedimientos (a diferencia de las funciones) no devuelven un único valor, sino que realizan una serie de acciones, su propósito principal es ejecutar tareas específicas en lugar de calcular y retornar un valor único.

Definición de un procedimiento

Se define utilizando la palabra clave procedure. La forma general de la definición de un procedimiento es la siguiente:

ejemplo de un procedimiento que acepta argumentos:

procedure nombre_procedimiento(param1: tipo1; param2: tipo2; ...);
// declaraciones locales usando `var`, si aplica

begin // <- el cuerpo del procedimiento, comienza con 'begin'
   sentencia1;
   sentencia2;
   ...
end // <- el cuerpo del procedimiento, finaliza con 'end'

ejemplo de un procedimiento que no acepta argumentos:

procedure nombre_procedimiento();
// declaraciones locales usando `var`, si aplica

begin // <- el cuerpo del procedimiento, comienza con 'begin'
   sentencia1;
   sentencia2;
   ...
end // <- el cuerpo del procedimiento, finaliza con 'end'

Parámetros: establecen el vínculo entre el programa de llamada y los identificadores del procedimiento, y también se denominan parámetros formales. Un parámetro es como un marcador de posición. Cuando se invoca a un procedimiento, se pasa un valor al parámetro. Este valor se denomina parámetro real o argumento. La lista de parámetros se refiere al tipo, el orden y el número de parámetros de un procedimiento. El uso de dichos parámetros formales es opcional. Estos parámetros pueden tener un tipo de dato estándar, un tipo de datos definido por el usuario o un tipo de datos de subrango.

Argumento: por otro lado, es el valor real que se pasa al procedimiento al momento de su invocación. Es el dato que ocupa la posición del parámetro definido en la cabecera.

resumiendo un poco:

  • Parámetros son las variable en la declaración del procedimiento.
  • Argumentos son los valores reales pasado en la llamada, usados en la invocación del procedimiento.

Declaraciones locales: las declaraciones locales se refieren a las declaraciones de etiquetas, variables, que se aplican únicamente al cuerpo del procedimiento.

Cuerpo del procedimiento: contiene un conjunto de sentencias que definen lo que hace el procedimiento. Siempre debe estar entre las palabras reservadas begin y end. Es la parte de un procedimiento donde se realizan todos los cálculos.

Llamar a un procedimiento

Al crear un procedimiento, se define lo que debe hacer dicho procedimiento. Para utilizar un procedimiento, hay que llamarlo(ó invocarlo) para que realice la tarea definida. Cuando un programa llama a un procedimiento, el control del programa se transfiere al procedimiento llamado, este realiza la tarea definida y, cuando se ejecuta su ultima instrucción, devuelve el control del programa, al programa principal.

Llamar/invocar a un procedimiento implica:

  • usar el nombre definido para él
  • enviarle argumentos (si los acepta)
// si el procedimiento recibe argumentos
nombre_procedimiento(arg1, arg2, ...);
// si el procedimiento NO recibe argumentos
nombre_procedimiento();

veamos un ejemplo

Ejemplo

program test_procedures;

procedure saludo(nombre: string);
begin
    writeln("Hola", nombre, "saludos desde un procedimiento");
end

begin
    saludo("Pedro");
end.

salida

la salida será algo como:

minipas v.1.9.0
Hola Pedro saludos desde un procedimiento

A tener en cuenta:

Recuerda que los procedimientos (definidos usando procedure) NO devuelven un valor.

Consideraciones

Definición clara: Asegúrate de que el procedimiento tenga un propósito específico y bien definido.

Nombres descriptivos: Usa nombres significativos que reflejen la acción que realiza el procedimiento (por ejemplo, saludo).

Número de parámetros y argumentos: Los argumentos deben coincidir en número y tipo con los parámetros definidos en el procedimiento.

Limita el número de parámetros para mantener la simplicidad.

Valor de retorno: Especifica el tipo de retorno del procedimiento claramente.

Documentación: Comenta el código para explicar qué hace el procedimiento, sus parámetros y en general que hace.

Evitando efectos secundarios: Trata de evitar modificar variables globales a menos que sea necesario; esto ayuda a mantener el procedimiento predecible.

Pruebas y validaciones: Implementa pruebas para garantizar que el procedimiento produzca los resultados esperados con varios datos de entrada.

Considera agregar validaciones de entrada para evitar errores.

Código modular: Divide la lógica del programa en funciones y procedimientos más pequeños y manejables; esto facilita la lectura y el mantenimiento del código.

Anidamiento: Puedes llamar a otras funciones y procedimientos dentro de un procedimiento, pero ten cuidado con la profundidad anidada para no complicar la lógica.

Gestión de errores: Implementa manejo de errores donde sea necesario para evitar fallos inesperados durante la ejecución.

Recursividad: Si usas procedimientos recursivos, asegúrate de tener una condición de salida clara para evitar bucles infinitos, La clave está en gestionar adecuadamente las condiciones de salida para asegurar que la recursión se detenga de manera adecuada.

Ciclos

En general, las sentencias se ejecutan secuencialmente: primero se ejecuta la primera sentencia de una función/procedimiento, seguida de la segunda, y así sucesivamente. Los lenguajes de programación proporcionan diversas estructuras de control que permiten rutas de ejecución más complejas.

Los bucles (ó ciclos) son otra estructura de control de flujo, que nos permite ejecutar algunas partes del código varias veces.

En este capítulo veremos tres tipos de bucles, disponibles en Minipas:

  • ciclo for: se ejecuta un número determinado de veces.
  • ciclo while: se ejecuta mientras se cumpla una condición.
  • ciclo repeat: ejecuta el bloque de código al menos una vez y luego continúa repitiéndolo hasta que se cumpla una condición.

for

El ciclo for for-do) se utiliza para iterar sobre un rango específico de valores. Es ideal cuando se conoce de antemano cuántas veces se debe repetir el bloque de código.

La sintaxis del bucle for-do es la siguiente:

to

La palabra clave to indica que el ciclo se ejecutará desde un valor inicial hasta un valor final, incrementando la variable de control en cada iteración.

for nombre_variable := valor_inicial to valor_final do 
  Sentencia;

usando un bloque begin/end (recomendado)

for nombre_variable := valor_inicial to valor_final do
  begin
    Sentencia1;
    Sentencia2;
    ...
  end

Donde:

nombre_variable especifica una variable de tipo ordinal, denominada variable de control o variable índice; los valores valor_inicial y valor_final son valores que puede tomar la variable de control; y Sentencia (ó Sentencia1, Sentencia2 …) es el cuerpo del bucle for-do, que puede ser una instrucción simple o un grupo de instrucciones.


A tener en cuenta:

La variable nombre_variable debe ser declarada antes de ser utilizada en el ciclo for.

Para el ciclo/bucle for se recomienda utilizar siempre un bloque begin/end.


Ejemplo

cuando existe una sola sentencia, se puede utilizar el ciclo for-do en una linea.

for i := 1 to 5 do writeln("hello foor loop in minipas", i);

sin embargo, por legibilidad, siempre recomendaremos el uso de un bloque begin/end.

for i := 1 to 5 do
begin
  writeln("hello foor loop in minipas", i);
end

salida

la salida para ambos casos, será algo como:

minipas v.1.9.0
hello foor loop in minipas 1
hello foor loop in minipas 2
hello foor loop in minipas 3
hello foor loop in minipas 4
hello foor loop in minipas 5

down-to

La palabra clave downto se utiliza para iterar de manera decreciente, comenzando desde un valor final hasta un valor inicial, decrementando la variable de control en cada iteración.

for nombre_variable := valor_final downto valor_inicial do 
  Sentencia;

usando un bloque begin/end (recomendado)

for nombre_variable := valor_final downto valor_inicial  do
  begin
    Sentencia1;
    Sentencia2;
    ...
  end

Donde:

nombre_variable especifica una variable de tipo ordinal, denominada variable de control o variable índice; los valores valor_inicial y valor_final son valores que puede tomar la variable de control; y Sentencia (ó Sentencia1, Sentencia2 …) es el cuerpo del bucle for-do, que puede ser una instrucción simple o un grupo de instrucciones.


A tener en cuenta:

La variable nombre_variable debe ser declarada antes de ser utilizada en el ciclo for.

Para el ciclo/bucle for se recomienda utilizar siempre un bloque begin/end.


Ejemplo

cuando existe una sola sentencia, se puede utilizar el ciclo for-do en una linea.

for i := 5 downto 1 do writeln("hello foor loop in minipas", i);

sin embargo, por legibilidad, siempre recomendaremos el uso de un bloque begin/end.

for i := 5 downto 1 do
begin
  writeln("hello foor loop in minipas", i);
end

salida

la salida para ambos casos, será algo como:

minipas v.1.9.0
hello foor loop in minipas 5
hello foor loop in minipas 4
hello foor loop in minipas 3
hello foor loop in minipas 2
hello foor loop in minipas 1

Recomendaciones

Definición clara de los límites: Asegúrate de que los límites de inicio y fin sean claros y correctos para evitar bucles que no se comportan como se esperaba.

Evitar bucles infinitos: Verifica que las condiciones de terminación de tus ciclos estén bien definidas para evitar que tu programa se quede atrapado en un bucle infinito.

Incrementos y decrementos correctos: En ciclos for, asegúrate de que el incremento (usando to) o el decremento (usando downto) sean apropiados para la lógica del programa.

Uso de variables de control: Mantén el uso de la variable de control (como i) simple y único dentro del ciclo para evitar confusiones y errores en la lógica.

Comentarios claros: Agrega comentarios para explicar la lógica detrás de los ciclos, especialmente si tienen condiciones complejas o no evidentes.

Ciclos anidados: Si utilizas ciclos anidados, mantén la claridad en el control de las variables para evitar errores lógicos y verifica que la lógica sea comprensible.

Preferir for para iteraciones contables: Usa for-do cuando sepas de antemano cuántas veces necesitas iterar, ya que es más legible y fácil de entender.

Evaluar el rendimiento: Considera el impacto en el rendimiento de bucles anidados o extensos, y optimiza cuando sea necesario para evitar problemas de eficiencia.

Pruebas exhaustivas: Realiza pruebas con diferentes valores de entrada para asegurar que los ciclos funcionan como se espera en todos los casos, especialmente en los límites.

Evitar lógica complicada dentro del ciclo: Mantén las instrucciones dentro del ciclo simples y directas. Si la lógica es compleja, considera extraerla en funciones o procedimientos separados.

while

El ciclo while(while-do) se repite mientras la condición especificada sea verdadera. Es útil cuando no se conoce de antemano el número de iteraciones.

La sintaxis del bucle while-do es la siguiente:

while condición do
begin
  Sentencia1;
  Sentencia2;
  ...
end

Condición: La expresión booleana que se evalúa antes de cada iteración. Si la condición es verdadera, el bloque de instrucciones se ejecuta. Si es falsa, el ciclo termina.

Recuerda que debes controlar la condición, para evitar caer en un ciclo infinito.


A tener en cuenta:

Aunque es posible hacer que un ciclo while ocupe una sola línea:

while condición do Sentencia;

se recomienda siempre utilizar un bloque begin/end.

Usar un estilo claro y mantener una buena legibilidad del código es fundamental para evitar errores en la lógica tu programa.


Ejemplo

  • ejemplo 1:

⚠️ Este ejemplo causa un bucle infinito, debido a que la sentencia termina en el punto y coma (;) despues de writeln y no al final del incremento de i;

program test_loops;
var i: integer;

begin
   i := 1; // inicializamos el valor de `i` en 1

   // este ejemplo causa un bucle infinito ⚠️
   while i <= 5 do writeln("el número es:", i); i := i + 1;
end.

por eso siempre se recomienda el uso de un bloque begin/end.

  • ejemplo 2:
program test_loops;
var i: integer;

begin
  i := 1; // inicializamos el valor de `i` en 1

  while i <= 5 do
  begin
    writeln("el número es:", i);
    i := i + 1; // incrementamos `i`
  end
end.

en el ejemplo anterior, la condición i <= 5 se evalúa en cada iteración del ciclo, y al final del bloque del ciclo se utiliza i := i + 1; como control, para poder validar la condición y poder salir del ciclo while-do.

salida

la salida será algo como:

minipas v.1.9.0
el número es:  1
el número es:  2
el número es:  3
el número es:  4
el número es:  5

Ejemplo

hagamos el clasico ejemplo de las tablas de multiplicar:

program test_loops;
var i,j: integer;
var resultado: integer;

begin
  writeln("tablas de multiplicar");
  writeln();

  // inicializamos el valor de `i` en 1
  i := 1;

  while (i <= 10) do // <- primer ciclo while
  begin
    // inicializamos el valor de `j` en 1
    // en cada iteración del ciclo principal
    j := 1;

    while j <= 10 do // <- ciclo while anidado
    begin
      resultado := i * j;
      writeln(i, " x ", j, " = ", resultado);
      j := j + 1; // incrementamos `j`
    end

    writeln("----------------------");
    i := i + 1; // incrementamos `i`
  end
end.

Aquí utilizamos ciclos anidados!.

salida

la salida será algo como:

minipas v.1.9.0
tablas de multiplicar

1  x  1  =  1
1  x  2  =  2
1  x  3  =  3
1  x  4  =  4
1  x  5  =  5
1  x  6  =  6
1  x  7  =  7
1  x  8  =  8
1  x  9  =  9
1  x  10  =  10
----------------------
2  x  1  =  2
2  x  2  =  4
2  x  3  =  6
2  x  4  =  8
2  x  5  =  10
2  x  6  =  12
2  x  7  =  14
2  x  8  =  16
2  x  9  =  18
2  x  10  =  20
----------------------
3  x  1  =  3
3  x  2  =  6
3  x  3  =  9
3  x  4  =  12
3  x  5  =  15
3  x  6  =  18
3  x  7  =  21
3  x  8  =  24
3  x  9  =  27
3  x  10  =  30
----------------------

...

Recomendaciones

Evitar bucles infinitos: Verifica que las condiciones de terminación de tus ciclos estén bien definidas para evitar que tu programa se quede atrapado en un bucle infinito.

Uso de variables de control: Mantén el uso de la variable de control (como i) simple y único dentro del ciclo para evitar confusiones y errores en la lógica.

Comentarios claros: Agrega comentarios para explicar la lógica detrás de los ciclos, especialmente si tienen condiciones complejas o no evidentes.

Ciclos anidados: Si utilizas ciclos anidados, mantén la claridad en el control de las variables para evitar errores lógicos y verifica que la lógica sea comprensible.

Evaluar el rendimiento: Considera el impacto en el rendimiento de bucles anidados o extensos, y optimiza cuando sea necesario para evitar problemas de eficiencia.

Pruebas exhaustivas: Realiza pruebas con diferentes valores de entrada para asegurar que los ciclos funcionan como se espera en todos los casos, especialmente en los límites.

Evitar lógica complicada dentro del ciclo: Mantén las instrucciones dentro del ciclo simples y directas. Si la lógica es compleja, considera extraerla en funciones o procedimientos separados.

repeat

A diferencia de los bucles for y while, que comprueban la condición del bucle en la parte superior del mismo, el bucle repeat … until comprueba su condición en la parte inferior del bucle.

Un ciclo/bucle repeat … until es similar a un bucle while, excepto que este garantiza que se ejecutará al menos una vez, y luego continúa repitiéndolo hasta que se cumpla una condición.

La sintaxis del bucle repeat … until es la siguiente:

repeat
   Setencia1;
   Setencia2;
   ...
   SetenciaN;
until condición;

Observa que la expresión condicional aparece al final del bucle, por lo que las instrucciones dentro, se ejecutan una vez antes de que se compruebe la condición.

Si la condición es falsa, el flujo de control vuelve al principio para repetirse, y las instrucciones del bucle se ejecutan de nuevo. Este proceso se repite hasta que la condición dada se vuelve verdadera.

A tener en cuenta:

Recuerda que debes controlar la condición, para evitar caer en un ciclo infinito.

El ciclo repeat … until no necesariamente necesita de un bloque begin/end.

Usar un estilo claro y mantener una buena legibilidad del código es fundamental para evitar errores en la lógica tu programa.


Ejemplo

program test_loops;
var
   i, j: integer;
   resultado: integer;

begin
   writeln("Tablas de multiplicar");
   writeln();

   // Inicializamos el valor de `i` en 1
   i := 1;

   repeat
      // Inicializamos el valor de `j` en 1
      j := 1;

      repeat
         resultado := i * j;
         writeln(i, " x ", j, " = ", resultado);
         j := j + 1; // incrementamos `j`
      until j > 10; // condición de terminación para el ciclo anidado

      writeln("----------------------");
      i := i + 1; // incrementamos `i`
   until i > 10; // condición de terminación para el ciclo principal
end.

salida

la salida será algo como:

minipas v.1.9.0
Tablas de multiplicar

1  x  1  =  1
1  x  2  =  2
1  x  3  =  3
1  x  4  =  4
1  x  5  =  5
1  x  6  =  6
1  x  7  =  7
1  x  8  =  8
1  x  9  =  9
1  x  10  =  10
----------------------
2  x  1  =  2
2  x  2  =  4
2  x  3  =  6
2  x  4  =  8
2  x  5  =  10
2  x  6  =  12
2  x  7  =  14
2  x  8  =  16
2  x  9  =  18
2  x  10  =  20
----------------------
3  x  1  =  3
3  x  2  =  6
3  x  3  =  9
3  x  4  =  12
3  x  5  =  15
3  x  6  =  18
3  x  7  =  21
3  x  8  =  24
3  x  9  =  27
3  x  10  =  30
----------------------

...

A tener en cuenta:

Recuerda que debes controlar la condición, para evitar caer en un ciclo infinito.

Recomendaciones

Evitar bucles infinitos: Verifica que las condiciones de terminación de tus ciclos estén bien definidas para evitar que tu programa se quede atrapado en un bucle infinito.

Uso de variables de control: Mantén el uso de la variable de control (como i) simple y único dentro del ciclo para evitar confusiones y errores en la lógica.

Comentarios claros: Agrega comentarios para explicar la lógica detrás de los ciclos, especialmente si tienen condiciones complejas o no evidentes.

Ciclos anidados: Si utilizas ciclos anidados, mantén la claridad en el control de las variables para evitar errores lógicos y verifica que la lógica sea comprensible.

Evaluar el rendimiento: Considera el impacto en el rendimiento de bucles anidados o extensos, y optimiza cuando sea necesario para evitar problemas de eficiencia.

Pruebas exhaustivas: Realiza pruebas con diferentes valores de entrada para asegurar que los ciclos funcionan como se espera en todos los casos, especialmente en los límites.

Evitar lógica complicada dentro del ciclo: Mantén las instrucciones dentro del ciclo simples y directas. Si la lógica es compleja, considera extraerla en funciones o procedimientos separados.

break y continue

break

Es una instrucción que se utiliza para salir inmediatamente de un ciclo (como for, while o repeat…until). Cuando se utiliza, control de flujo se transfiere a la siguiente línea después del ciclo que contiene la instrucción break.

program breakExample;
var a: integer;

begin
   a := 10;

   while a < 20 do
   begin
      writeln("el valor de a es:", a);
      a:= a+1;

      if a > 15 then
        break; // <- uso de break
   end
end.

la salida será algo como

minipas v.1.9.0
el valor de a es: 10
el valor de a es: 11
el valor de a es: 12
el valor de a es: 13
el valor de a es: 14
el valor de a es: 15

continue

Esta instrucción se utiliza para saltar directamente a la siguiente iteración de un ciclo. Al encontrar un continue, el resto del código en la iteración actual se omite y se pasa a la siguiente.

En el bucle for, la instrucción continue hace que se ejecuten las partes de prueba condicional e incremento del bucle. En los bucles while y repeat...until, la instrucción continue hace que el control del programa pase a las pruebas condicionales.

program continueExample;
var i: integer;

begin
   for i := 1 to 10 do
   begin
      if i mod 2 = 0 then
         continue; // salta la iteración para números pares
      writeln("número impar:", i);
   end
end.

la salida será algo como

minipas v.1.9.0
número impar: 1
número impar: 3
número impar: 5
número impar: 7
número impar: 9

goto

⚠️ Minipas no admite la sentencia goto.

Recomendaciones

al utilizar break:

Claridad: Usa break solamente cuando sea necesario salir de un ciclo prematuramente, demasiados break pueden hacer que el flujo del código sea confuso.

Uso Moderado: si encuentras que estás usando break frecuentemente, considera reestructurar el ciclo o la lógica para que sea más clara.

Documenta su Uso: comenta por qué es necesario para que futuros lectores del código comprendan la lógica detrás de su uso.


al utilizar continue:

Claridad: usa continue para mejorar la legibilidad del código al evitar anidamientos excesivos de condicionales dentro de un ciclo.

Cuidado con Saltos: asegúrate de que utilizar continue no cause que se omitan acciones críticas en el ciclo.

Comentarios: similar a break, documenta el uso de continue, haciendo explícito el motivo de saltar ciertas iteraciones.

Funciones integradas

Las funciones integradas (o built-in functions) son funciones predefinidas que están disponibles en Minipas sin necesidad de que el programador las defina explícitamente. Estas funciones permiten realizar operaciones comunes y son parte del runtime del lenguaje, facilitando tareas de programación frecuentes.

Características

Disponibilidad: Están siempre accesibles durante la programación sin necesidad de definiciones adicionales o importaciones.

Tipos de Operaciones: Realizan una variedad de tareas, incluyendo:

  • Manipulación de cadenas.
  • Operaciones matemáticas.
  • Entrada y salida de datos.
  • Conversión de tipos de datos.

y muchas cosas más!.

Ventajas

  • Ahorro de Tiempo: Permiten realizar tareas complejas sin necesidad de codificarlas desde cero.
  • Reducción de Errores: Al utilizar funciones ya probadas y testeadas, se minimizan los errores en el código.
  • Facilidad de Mantenimiento: El uso de funciones integradas puede hacer el código más limpio y fácil de mantener.

Lista de funciones integradas

A continuación se describe la lista de funciones integradas en Minipas.

entrada/salida

  • writeln: Escribe un texto en la salida estándar y añade un salto de línea al final.
writeln("hola mundo en minipas!");
  • write: Escribe un texto en la salida estándar sin añadir un salto de línea.
write("esto");
write("va");
write("en");
write("la");
write("misma");
write("linea");
// la salida será algo como:
esto va en la misma linea
  • readln: Lee una línea de texto de la entrada estándar y la asigna a una variable.
writeln("Escriba un nombre");
name:= readln();
writeln("el nombre es:", name);
  • format: Da formato a cadenas de texto, permitiendo la inclusión de variables de manera estructurada.

constantes

  • PI: Constante que representa el valor de π (pi), aproximadamente 3.141592653589793.
writeln("el valor de PI es:", PI);
  • E: Constante que representa el número e (conocido en ocasiones como número de Euler o constante de Napier), la base del logaritmo natural, aproximadamente 2.718281828459045.
writeln("el valor de E es:", E);

funciones matemáticas básicas

  • pow: Calcula la potencia de un número dado, elevando una base a un exponente.
a := 2;
b := 8;
writeln("2^8 = ", pow(a, b));
  • abs: Devuelve el valor absoluto de un número, eliminando cualquier signo negativo.
writeln("abs(0)", abs(0));
writeln("abs(-1)", abs(-1));
writeln("abs(-1.25)", abs(-1.25));
writeln("abs(1.234)", abs(1.234));

funciones trigonométricas

  • sin: Calcula el seno de un ángulo dado en radianes.
writeln("sin(-1.234)", sin(-1.234));
  • cos: Calcula el coseno de un ángulo dado en radianes.
writeln("cos(-1.234)", cos(-1.234));
  • tan: Calcula la tangente de un ángulo dado en radianes.
writeln("tan(PI/4) = ", tan(PI/4));
  • cot: Calcula la cotangente de un ángulo dado en radianes.
writeln("cot(PI/4) = ", cot(PI/4));
  • asin: Calcula el arco seno, retornando el ángulo correspondiente a un valor dado.
writeln("asin(1) = ", asin(1));
  • acos: Calcula el arco coseno, retornando el ángulo correspondiente a un valor dado.
writeln("acos(0) = ", acos(0));
  • atan: Calcula el arco tangente, retornando el ángulo correspondiente a un valor dado.
writeln("atan(1) = ", atan(1));

funciones logarítmicas y exponenciales

  • exp: Calcula el valor de e elevado a la potencia de un número.
writeln("exp(1) = ", exp(1));
  • ln: Devuelve el logaritmo natural (base e) de un número.
writeln("ln(E) = ", ln(E));
  • log10: Calcula el logaritmo en base 10 de un número.
writeln("log10(100) = ", log10(100));
  • sqrt: Devuelve la raíz cuadrada de un número.
writeln("sqrt(16) = ", sqrt(16));

funciones auxiliares

  • floor: Retorna el mayor número entero menor o igual al número dado.
writeln("floor(3.7) = ", floor(3.7));
  • ceil: Retorna el menor número entero mayor o igual al número dado.
writeln("ceil(3.2) = ", ceil(3.2));
  • round: Redondea un número al entero más cercano.
writeln("round(2.6) = ", round(2.6));
  • trunc: Elimina la parte decimal de un número, retornando solo la parte entera.
writeln("trunc(-2.71828) = ", trunc(-2.71828));
  • fract: Devuelve la parte fraccionaria de un número.
⚠️ missing example
  • max: Retorna el mayor de dos o más números proporcionados.
writeln("max(3,7) = ", max(3,7));
  • min: Retorna el menor de dos o más números proporcionados.
writeln("min(3,7) = ", min(3,7));
  • sign: Devuelve el signo de un número: 1 si es positivo, -1 si es negativo, y 0 si es cero.
writeln("sign(-5) = ", sign(-5));
writeln("sign(0) = ", sign(0));
writeln("sign(7) = ", sign(7));

sistema

  • random: Genera un número aleatorio dentro de un rango especificado, el valor debe ser mayor que cero (0)
writeln("funcion random 1:", random(0)); // <- genera un error ⚠️
writeln("funcion random 2:", random(1));
writeln("funcion random 3:", random(10));
writeln("funcion random 4:", random(1.234));
  • exit: Termina la ejecución del programa en cualquier punto.
program testSys;
begin
	writeln("usando el modulo sys");
	exit();
	writeln("terminado"); // nunca se ejecuta
end.
  • clrscr: Limpia la pantalla de la consola, eliminando todo el texto visible.
program testSys;
begin
    clrscr();
end.
  • typeinfo: Proporciona información sobre el tipo de dato de una variable en tiempo de ejecución.
writeln("uso de Integer:", typeinfo(123));
writeln("uso de toString:", typeinfo(123.toString()));

fechas

  • date: Retorna la fecha actual del sistema en un formato específico.
writeln("Fecha actual:", date());
  • time: Retorna la hora actual del sistema en un formato específico.
writeln("Hora actual:", time());
  • date_time: Devuelve la fecha y hora actuales combinadas en un solo valor.
writeln("Fecha y hora:", date_time());

cadenas de caracteres

  • len: Retorna la longitud de una cadena de caracteres.
cadena:= " Anita lava la tinA ";
total := len(cadena);
writeln("la cantidad de caracteres es (len):", total);
  • concat: permite unir dos ó más valores en una cadena de caracteres.
writeln("concatenar:", concat("caracteres", "y", PI, "ademas", "de", 1.234));

conversiones de tipos

  • to_int: Convierte un valor a su representación entera.
writeln("Ingresa un número entero");
num1 := to_int(readln());
  • to_real: Convierte un valor a su representación de punto flotante (real).
writeln("Ingresa un número con parte decimal");
num2 := to_real(readln());
  • to_str: Convierte un valor a su representación como cadena de texto.
writeln(42.to_str());
writeln(True.to_str());

pruebas

  • assert: Verifica si una condición es verdadera y genera un error si no lo es.
assert((4 % 2) = 0);
  • assert_equals: Compara dos valores y asegura que sean iguales, generando un error si no lo son.
assert_equals(1, 1);
assert_equals(True, False);
  • panic: Termina el programa y despliega un mensaje de error en caso de una situación crítica, espera un argumento.
program testSys;
begin
	panic("error al salir!");
	writeln("terminado"); // nunca se ejecuta
end.

Testing

Aunque Turbo Pascal V7 (del cual se inspira Minipas) no existía la función assert, en Minipas se incluye para comprobar condiciones y manejar errores de una manera más controlada en tu programa.

A tener en cuenta:

El uso de assert y de assert_equals causan pánico (el programa se detiene) si las condiciones no se cumplen:


assert

verifica que una condición sea verdadera. Si la condición no se cumple, se lanza una excepción y se detiene la ejecución del programa, indicando que se ha producido un error.

Ejemplo

program testExample;
var a,b:integer;
begin
    a:= 1;
    b:= 1;
    
    assert(2 * 2 = 4);
    assert(a<>b); // <- falla
end.

Salida

la salida es algo como:

minipas v.1.9.0

thread 'main' panicked at src\runtime\std_lib\testing.rs:11:13:
Assertion failed: expected `true`, got `false`

assert_equals

compara dos valores: uno esperado y otro real. Si los valores no son iguales, se lanza una excepción y se detiene la ejecución del programa, indicando que se ha producido un error.

Ejemplo

program testSys;
var msg1: string;
begin

msg1 := "Hola";
assert_equals(msg1.lower(), "hola");
writeln();

writeln("el valor de PI es:", PI);
assert_equals(PI, 3.141592); // <- falla
end.

Salida

la salida es algo como:

minipas v.1.9.0

el valor de PI es: 3.141592653589793

thread 'main' panicked at src\runtime\std_lib\testing.rs:46:9:
Assertion failed: expected left: `3.141592653589793`, got right: `3.141592`

Apéndice I: Palabras clave

Minipas no tiene palabras claves en sí, sin embargo hace uso intensivo de las siguientes:

integer
real
boolean
byte
begin
div
else
if
mod
not
program
repeat
string
then
until
var
while
True
False
writeln
write
readln
do
to
downto
end
for
function
procedure
nil

Guía de estilo

Minipas 1.9.0

Este documento define el estilo oficial de código para Minipas. Su objetivo es garantizar que todos los programas escritos en Minipas sean:

  • claros
  • consistentes
  • fáciles de leer
  • simples de mantener
  • didácticos

La guía se inspira en prácticas de Free Pascal, GNU Pascal, Object Pascal y otras guías de estilo.

1. Filosofía del lenguaje

Minipas toma muchas caracteristicas y referencias del lenguage Pascal, sin embargo, hay que recalcar algunas cosas:

  • ⚠️ MiniPas no busca ser compatible con Pascal, Turbo Pascal V7 ó FreePascal: muchas características de Pascal no están soportadas.

  • MiniPas es un lenguaje interpretado, inspirado en Turbo Pascal V7, diseñado para ser sencillo, educativo y fácil de usar, la gran mayoría (si no todos…) de los dialectos de Pascal son compilados.

  • Pascal es un lenguaje que no distingue entre mayúsculas y minúsculas (Case Insensitive), lo que significa que puedes escribir tus variables, funciones y procedimientos con cualquiera de las dos. En Minipas no se acepta esto, todas las palabras claves deben escribirse en minúsculas, salvo muy pequeñas excepciones.

  • En minipas, cada sentencia debe terminar en punto y coma (;).

  • ☢️ MiniPas Es un lenguaje experimental y minimalista.

  • Minipas es un lenguaje minimalista y educativo, por lo que la guía enfatiza:

    • simplicidad sobre optimización
    • claridad sobre trucos
    • coherencia sobre preferencias personales

Cuando existan dudas, elegir siempre lo más legible.

2. Organización de archivos

2.1 Un archivo, un programa

Cada archivo de Minipas debe contener un único programa o módulo.

2.2 Nombre del archivo

Utilizar siempre minúsculas y evitar espacios:

calculadora.mp
mi_programa.mp

2.3 Estructura básica del archivo

Un archivo debe seguir este orden lógico:

# Comentarios iniciales / propósito
# Declaraciones globales (si las hay)
# Programa principal

Mantener el archivo limpio y sin secciones huérfanas.


3. Estilo de nombres

Minipas adopta un estilo snake_case simple, consistente y fácil de leer.

3.1 Variables

  • minúsculas
  • palabras separadas con _
  • nombres descriptivos

Ejemplos:

contador
suma_total
nombre_usuario

3.2 Constantes

⚠️ Minipas no admite constantes, cuando llegue el momento…

  • MAYÚSCULAS
  • separadas por _

Ejemplo:

MAX_INTENTOS = 3;
PI = 3.14159;

3.3 Funciones / procedimientos

Igual que las variables:

leer_archivo();
calcular_area(base, altura);

3.4 Boleanos

De ser necesario, preferir nombres que indiquen verdadero/falso:

es_valido
tiene_error
modo_debug

4. Formato e indentación

4.1 Indentación estándar

Usar 2 espacios por nivel. No usar tabs.

Ejemplo:

if x > 0 then
  writeln("positivo");

4.2 Líneas

  • longitud recomendada: máximo 120 caracteres
  • sin espacios al final

4.3 Espacios alrededor de operadores

Correcto:

a := b + c;
x := y * 2;

Incorrecto:

a:=b+c;

4.4 Paréntesis

Sin espacios internos:

Correcto:

imprimir(x + 1);

Incorrecto:

imprimir( x + 1 );

5. Bloques y estructuras de control

5.1 Bloques siempre multilínea

Siempre abrir un bloque en la línea siguiente.

Correcto:

program test_loops;
var i: integer;

begin
  i := 1;

  while i <= 5 do
  begin
    writeln("el número es:", i);
    i := i + 1;
  end
end.

Incorrecto:

program test_loops;
var i: integer;

begin
   while i <= 5 do writeln("el número es:", i); i := i + 1;
end.

5.2 Estructura de control estándar

If:

if condicion then
  Sentencia1;
else
  Sentencia2;

Bucle:

while condicion do
begin
  Sentencia1;
  Sentencia2;
  ...
  SentenciaN;
end

5.3 Evitar goto

⚠️ Minipas no admite la sentencia goto.

6. Comentarios

6.1 Comentarios de línea

Usar //.

// Este bucle acumula el total

6.2 Comentar el por qué, no el qué

❌ No útil:

// suma dos números
suma := a + b;

✔ Mejor:

// Reiniciamos suma para evitar arrastre de valores previos
suma := a + b;

6.3 Comentarios de bloque

Permitido para documentación o explicaciones largas:

{
 Este módulo valida el archivo de entrada,
 convierte el contenido a una estructura útil
 y luego ejecuta el programa principal.
}

7. Buenas prácticas del lenguaje

7.1 Código simple y claro

Evitar expresiones complejas. Evitar magia o algoritmos innecesariamente enredados.

7.2 No duplicar código

Extraer funciones cuando sea posible.

7.3 Evitar efectos colaterales ocultos

Una función debería hacer solo una cosa.

7.4 Inicializar variables

No depender de valores implícitos.

7.5 Manipulación defensiva

Comprobar casos especiales si aplica (divisiones, rangos, etc.).


8. Ejemplos oficiales

8.1 Ejemplo completo

{
	La sucesión de Fibonacci es una sucesión `Fn` de números
	naturales definida de forma recursiva.

	- https://www.calculatorsoup.com/calculators/discretemathematics/fibonacci-calculator.php
	- https://rosettacode.org/wiki/Fibonacci_sequence
}

program test_fibonacci;
var numero, resultado: integer;

function fibonacci(num:integer): integer;
begin
	if num < 2 then
		return num;
	return fibonacci(num-1) + fibonacci(num-2);
end

begin
	writeln("calcular numeros de fibonacci");
	writeln("Introduce un número entero (no muy grande)");
	numero := to_int(readln());
	resultado := fibonacci(numero);
	writeln("el fibonacci de", numero, "es",  resultado);
end.

9. Errores comunes a evitar

  • nombres como x, t, c1 sin contexto
  • bloques en una sola línea
  • comentarios redundantes
  • confiar en comportamiento no definido
  • mezclar estilos
  • indentación inconsistente

10. Resumen rápido (cheat-sheet)

  • Indentación: 2 espacios
  • Nombres: snake_case
  • Constantes: cuando se soporten serán en MAYÚSCULAS
  • Bloques: siempre multilínea
  • Comentarios: explicar el porqué
  • Longitud de línea: 120 caracteres
  • Priorizar: claridad, simpleza, consistencia