Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions docs/Features/Standard-Library/File-IO.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,4 @@ Open "C:\MyFile.txt" For Input Encoding utf-8 As #1

## Supported Encodings

The full list of encoding options currently defined (and don't worry, these will come up in Intellisense) is:

- `default_system_ansi`
- `utf_7`, `utf_7_bom`
- `utf_8`, `utf_8_bom`
- `utf_16`, `utf_16_bom`
- `us_ascii`
- `koi8_u`, `koi8_r`
- `big5`
- `iso_8859_1_latin1`, `iso_8859_2_latin2`, `iso_8859_3_latin3`, `iso_8859_4_latin4`
- `iso_8859_5_cyrillic`, `iso_8859_6_arabic`, `iso_8859_7_greek`, `iso_8859_8_hebrew`
- `iso_8859_9_latin5_turkish`, `iso_8859_10_latin6_nordic`, `iso_8859_11_thai`
- `iso_8859_13_latin8_baltic`, `iso_8859_14_latin8_celtic`
- `iso_8859_15_latin9_euro`, `iso_8859_16_latin10_balkan`
- `windows_1250_central_europe`, `windows_1251_cyrillic`, `windows_1252_western`
- `windows_1253_greek`, `windows_1254_turkish`, `windows_1255_hebrew`, `windows_1256_arabic`
- `windows_1257_baltic`, `windows_1258_vietnamese`
- `ibm_850_western_europe`, `ibm_852_central_and_eastern_europe`
- `ibm_855_cyrillic`, `ibm_856_hebrew`, `ibm_857_turkish`, `ibm_858_western_europe`
- `ibm_860_portuguese`, `ibm_861_icelandic`, `ibm_862_hebrew`
- `ibm_863_canadian`, `ibm_865_danish`, `ibm_866_cyrillic`, `ibm_869_greek`
- `ibm_932_japanese`, and `ibm_949_korean`

Others with a similar format should be accepted depending on system support.
See the [TextEncodingConstants module](../../tB/Modules/TextEncodingConstants/).
31 changes: 31 additions & 0 deletions docs/Reference/Modules/Compilation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,37 @@ has_toc: false

# Compilation module

The **Compilation** module groups together intrinsics that report on how — and from where — the running code was built. Most of its members are *compile-time* intrinsics: they do not look anything up at run time but instead bake a literal value into the compiled code at the point of the call, recording the surrounding project, component, procedure, or source file as it stood when the compiler ran.

## Build identity

[**CompilerVersion**](CompilerVersion) returns the build number of the twinBASIC compiler that produced the running code, and [**ProcessorArchitecture**](ProcessorArchitecture) returns a [**VbArchitecture**](../Constants/VbArchitecture) constant — **vbArchWin32** or **vbArchWin64** — identifying whether the binary was built for 32-bit or 64-bit execution. Together they characterise *which* compiler emitted the running code and *what kind* of process it is running in.

```tb
Debug.Print "twinBASIC build #" & CompilerVersion()
If ProcessorArchitecture() = vbArchWin64 Then
Debug.Print "64-bit process"
Else
Debug.Print "32-bit process"
End If
```

## Lexical context

The `Current...` family records the source location of the call site as a literal string, captured when the source is compiled. [**CurrentProjectName**](CurrentProjectName) names the project (executable or library) that owns the call, [**CurrentComponentName**](CurrentComponentName) names the enclosing module, class, or form, [**CurrentProcedureName**](CurrentProcedureName) names the surrounding **Sub**, **Function**, or **Property**, and [**CurrentSourceFile**](CurrentSourceFile) returns the full path of the source file as it was on the build machine. For COM classes, [**CurrentComponentCLSID**](CurrentComponentCLSID) returns the GUID supplied by the class's [`[ClassId(...)]`](../../Core/Attributes#classid) attribute, or the all-zero GUID when none is set.

Because each value is fixed at compile time, wrapping a call in a helper records the *helper's* name rather than its caller's. These intrinsics are most useful in diagnostic output — logging, tracing, assertions — where they replace hard-coded identifier strings that would otherwise drift as code is renamed.

```tb
Public Sub Log(Message As String)
Debug.Print CurrentProjectName() & "!" & _
CurrentComponentName() & "." & _
CurrentProcedureName() & ": " & Message
End Sub
```

## Members

- [CompilerVersion](CompilerVersion) -- returns the twinBASIC compiler version number
- [CurrentComponentCLSID](CurrentComponentCLSID) -- returns the Class ID (CLSID) of the current class
- [CurrentComponentName](CurrentComponentName) -- returns the name of the current component (module or class)
Expand Down
57 changes: 57 additions & 0 deletions docs/Reference/Modules/Conversion/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,63 @@ has_toc: false

# Conversion module

The **Conversion** module groups together the procedures that produce a value of one type from a value of another — coercing between the intrinsic numeric types, parsing numbers out of strings, formatting numbers as strings, and a handful of related utilities for handling **Null**, error values, and alternate numeric bases.

## Coercing to a specific type

The largest group is the family of **C**-prefixed functions, one per intrinsic data type. Each accepts any valid expression and produces a value of the named type, raising a run-time error if the conversion is not possible: [**CBool**](CBool), [**CByte**](CByte), [**CCur**](CCur), [**CDate**](CDate), [**CDbl**](CDbl), [**CDec**](CDec), [**CInt**](CInt), [**CLng**](CLng), [**CLngLng**](CLngLng), [**CLngPtr**](CLngPtr), [**CSng**](CSng), [**CStr**](CStr), and [**CVar**](CVar).

Beyond their narrowing or widening behaviour, the C-prefix functions are *locale-aware* — they honour the current decimal separator and short date format — which makes them the right choice for parsing values that originated as user input. They also serve as documentation: writing `CLng(x)` makes the intended type of an intermediate result explicit even where the surrounding context would coerce *x* implicitly.

```tb
Dim Amount As Currency
Amount = CCur("1,234.56") ' parses with the local decimal separator
```

Two further constructors return a **Variant** whose subtype is fixed: [**CVDate**](CVDate) builds a **Variant** of subtype **Date** (kept for compatibility with code written before **Date** became an intrinsic type), and [**CVErr**](CVErr) builds a **Variant** of subtype **Error** carrying a chosen error number — the canonical way for a **Variant**-returning function to signal "this call failed with this error code" without raising a run-time error.

## Generic conversion

[**CType**](CType) is a twinBASIC extension that takes its target type as a generic parameter, written `CType(Of `*type*`)(`*value*`)`. It plays the same role as the C-prefix functions but for any type known to the compiler, which makes it the standard cast for **Enum** values, interfaces, and user-defined types where no fixed-name function exists. **CType** doubles as a pointer-to-UDT cast — see [Enhanced Pointer Functionality](../../../Features/Language/Pointers#ctypeof-type).

```tb
Dim day As VbDayOfWeek
day = CType(Of VbDayOfWeek)(1)
```

## Truncating to an integer

[**Int**](Int) and [**Fix**](Fix) both discard the fractional part of a number, but they round in opposite directions for negative input. **Int** rounds toward negative infinity, so `Int(-8.4)` is `-9`; **Fix** truncates toward zero, so `Fix(-8.4)` is `-8`. For positive values the two coincide. Neither changes the data type of its argument, in contrast to [**CInt**](CInt) and [**CLng**](CLng), which both round and narrow to a specific integer type.

```tb
Debug.Print Int(-8.4) ' -9
Debug.Print Fix(-8.4) ' -8
```

## Numbers, strings, and bases

[**Str**](Str), [**Hex**](Hex), and [**Oct**](Oct) all return a printable string representation of a number — **Str** in decimal, **Hex** in base 16, and **Oct** in base 8. Going the other way, [**Val**](Val) and [**ValDec**](ValDec) parse leading digits out of a string, returning a **Double** or **Decimal** respectively; both stop at the first unrecognised character and both honour the `&H` and `&O` radix prefixes for hexadecimal and octal literals.

These five functions are *culture-invariant* — they always use the period (`.`) as the decimal separator and never read or write a thousands separator — which makes them appropriate for round-tripping through a fixed file format or wire protocol. For locale-aware conversion to and from text, use [**CStr**](CStr) and [**CDbl**](CDbl) (or [**CDec**](CDec)) instead.

```tb
Debug.Print Hex(255) ' "FF"
Debug.Print Oct(8) ' "10"
Debug.Print Val("&HFF") ' 255
```

## Working with Null and error values

[**Nz**](Nz) returns a substitute value when its argument is **Null**, leaving any other value unchanged. It is most useful for reading nullable columns from a database recordset, where directly concatenating or arithmetically combining the field with another value would otherwise propagate **Null** through the rest of the expression.

[**Error**](Error) returns the descriptive text associated with an error number — the same text that would appear as the **Description** of an [**ErrObject**](../ErrObject) raised with that number. It is the function counterpart to the same-named [**Error** statement](../../Core/Error), which *raises* a run-time error rather than describing one.

## Macintosh compatibility

[**MacID**](MacID) packs a four-character Macintosh resource type or application signature into a **Long** for use with [**Dir**](../FileSystem/Dir), [**Kill**](../FileSystem/Kill), **Shell**, or [**AppActivate**](../Interaction/AppActivate). twinBASIC currently targets Windows, where the value has no special meaning to those functions; **MacID** is provided for source compatibility with VBA code originally written for the classic Mac.

## Members

- [CBool](CBool) -- converts an expression to a **Boolean**
- [CByte](CByte) -- converts an expression to a **Byte**
- [CCur](CCur) -- converts an expression to a **Currency**
Expand Down
57 changes: 57 additions & 0 deletions docs/Reference/Modules/DateTime/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,63 @@ has_toc: false

# DateTime module

The **DateTime** module groups together the procedures for reading the system clock, building **Date** values from their components, parsing them out of strings, taking them apart again, and shifting them forward or backward by a chosen unit. A single setting — the [**Calendar**](Calendar) property — switches the whole module between the Gregorian and Hijri calendars.

## Reading the system clock

[**Now**](Now) returns the current system date *and* time as a single **Variant** of subtype **Date**; [**Date**](Date) returns just the date portion and [**Time**](Time) just the time portion. Each of the latter two has a `$`-suffixed sibling — **Date$** and **Time$** — that returns the same value as a formatted **String** rather than a **Date**. All four are also writable: assigning to them changes the system clock, subject to the operating system's privilege requirements.

> [!NOTE]
> In twinBASIC, **Date**, **Date$**, **Time**, and **Time$** are implemented as module-level properties rather than the functions/statements they were in VBx. The syntax and semantics are otherwise unchanged.

[**Timer**](Timer) returns a **Single** giving the number of seconds — with fractional precision — elapsed since midnight, and is the conventional way to measure elapsed time within a run.

```tb
Dim Started As Single
Started = Timer
' ... do some work ...
Debug.Print "Elapsed: " & (Timer - Started) & " seconds"
```

## Building dates and times from components

[**DateSerial**](DateSerial) builds a **Date** from year, month, and day arguments; [**TimeSerial**](TimeSerial) builds one from hour, minute, and second. Both honour out-of-range arguments by carrying — passing 13 as the month rolls into the next year, and passing 75 as the minute rolls into the next hour — which makes them well-suited to expressing relative dates as plain arithmetic on the components.

```tb
Dim FirstOfNextMonth As Date
FirstOfNextMonth = DateSerial(Year(Now), Month(Now) + 1, 1)
```

[**DateValue**](DateValue) parses a date out of a string in the system's short date format — recognising both numeric forms and unambiguous month names — and discards any time portion. [**TimeValue**](TimeValue) is the corresponding parser for time strings; it discards any date portion. For values that originate as date literals in source code, the surrounding `#...#` syntax is usually a better fit than either parser.

## Extracting parts of a date

The single-component accessors each return one part of a **Date** as an **Integer**: [**Year**](Year), [**Month**](Month), [**Day**](Day), [**Weekday**](Weekday), [**Hour**](Hour), [**Minute**](Minute), and [**Second**](Second). [**DatePart**](DatePart) generalises the same idea, taking the chosen part as a string interval code (`"yyyy"`, `"q"`, `"m"`, `"d"`, ...) — useful when the unit itself is a parameter.

```tb
Dim D As Date
D = #2/12/1969#
Debug.Print Year(D) ' 1969
Debug.Print Month(D) ' 2
Debug.Print Day(D) ' 12
Debug.Print Weekday(D) ' 4 — Wednesday
```

## Date arithmetic

[**DateAdd**](DateAdd) shifts a date by a chosen number of intervals — years, quarters, months, weeks, days, hours, minutes, or seconds — taking calendar irregularities (varying month lengths, leap years) into account, and clamping to the last day of the target month when a literal day-of-month would be invalid. [**DateDiff**](DateDiff) does the inverse: it returns the count of whole intervals between two dates. Both share the same string interval codes used by **DatePart**.

```tb
Debug.Print DateAdd("m", 1, #1/31/2026#) ' 2/28/2026 — clamped to last day of February
Debug.Print DateDiff("d", #1/1/2026#, #5/9/2026#) ' 128
```

## Calendar selection

The [**Calendar**](Calendar) property selects the calendar — **vbCalGreg** (Gregorian, the default) or **vbCalHijri** (Hijri) — used by the rest of the module. The setting controls how **Date$** formats the system date, how arguments to **DateSerial**, **DateValue**, **DateAdd**, and **DateDiff** are interpreted, and how the parts returned by **DatePart**, **Year**, **Month**, **Day**, and **Weekday** are reported.

## Members

- [Calendar](Calendar) -- returns or sets the calendar type (Gregorian or Hijri)
- [Date](Date) -- sets or returns the current system date
- [DateAdd](DateAdd) -- adds a time interval to a date
Expand Down
65 changes: 64 additions & 1 deletion docs/Reference/Modules/FileSystem/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,72 @@ has_toc: false

# FileSystem module

The **FileSystem** module groups together the procedures and statements for working with files and directories on disk. Its members divide cleanly into two camps: *pathname-based* operations that act on something named in the filesystem, and *file-number-based* operations that act on a handle previously returned by the **Open** statement.

## Navigating directories

[**ChDrive**](ChDrive) changes the current drive, [**ChDir**](ChDir) changes the current directory on a given drive, and [**CurDir**](CurDir) returns the path of the current drive — or of any other drive, if one is named. [**MkDir**](MkDir) and [**RmDir**](RmDir) create and remove directories.

```tb
ChDrive "D"
ChDir "D:\Projects"
Debug.Print CurDir ' "D:\Projects"
MkDir "D:\Projects\Output"
```

## Inspecting files and directories

[**Dir**](Dir) is the wildcard matcher: pass it a pathname containing `*` or `?` and it returns the first matching name, then call it again with no arguments to step through subsequent matches until it returns `""`. [**FileLen**](FileLen) returns the size of a file in bytes without opening it, and [**FileDateTime**](FileDateTime) returns its last-modified timestamp. [**GetAttr**](GetAttr) and [**SetAttr**](SetAttr) read and write the [**VbFileAttribute**](../Constants/VbFileAttribute) flag bits — read-only, hidden, system, archive — and **GetAttr** also reports whether a name refers to a directory by setting the **vbDirectory** bit.

```tb
Dim Name As String
Name = Dir("C:\Logs\*.log")
Do While Name <> ""
Debug.Print Name & vbTab & FileLen("C:\Logs\" & Name)
Name = Dir
Loop
```

## Copying and deleting

[**FileCopy**](FileCopy) copies one file to another, and [**Kill**](Kill) deletes files matching a wildcard pattern. Both operate by pathname and raise a run-time error when asked to act on a file the current process has open.

```tb
FileCopy "C:\Data\report.xlsx", "C:\Backup\report.xlsx"
Kill "C:\Backup\*.tmp"
```

## Opening and tracking file numbers

The lower-level read/write statements — **Open**, **Close**, **Get**, **Put**, **Print**, **Write**, **Input**, and **Line Input** — work in terms of a *file number* in the range 1–511. [**FreeFile**](FreeFile) returns the next number that isn't currently in use, sparing the caller from picking one by hand and racing other code to it. Once a file is open, [**FileAttr**](FileAttr) reports the access mode — **Input**, **Output**, **Random**, **Append**, or **Binary** — that the file number was opened with. [**Reset**](Reset) closes every file number currently open and flushes its buffers, and is most useful as a last-ditch cleanup before exit.

```tb
Dim N As Long
N = FreeFile
Open "C:\Data\report.txt" For Input As #N
' ... read ...
Close #N
```

## Position within an open file

For an open file number, [**EOF**](EOF) returns **True** once a sequential read has run past the last record, [**LOF**](LOF) returns the file's total length in bytes, and [**Loc**](Loc) returns the current read/write position. The unit of *position* depends on the open mode — record number for **Random**, byte offset for **Binary**, and the byte position divided by 128 for sequential modes — so the per-mode tables on each function's page are the authoritative reference. [**Seek**](Seek) doubles as a function and a statement: the function returns the position of the **next** read or write (whereas **Loc** reports the position of the *last*), and the statement repositions the file pointer ahead of the next operation.

```tb
Dim N As Long, Line As String
N = FreeFile
Open "C:\Data\big.log" For Input As #N
Do While Not EOF(N)
Line Input #N, Line
Loop
Close #N
```

## Members

- [ChDir](ChDir) -- changes the current directory or folder
- [ChDrive](ChDrive) -- changes the current drive
- [CurDir](CurDir) -- returns the current path
- [Dir](Dir) -- returns the name of a file, directory, folder, or volume label that matches a pattern
- [EOF](EOF) -- returns whether the end of a file opened for **Random** or sequential **Input** has been reached
- [FileAttr](FileAttr) -- returns the file mode for files opened with the **Open** statement
Expand All @@ -21,7 +85,6 @@ has_toc: false
- [Loc](Loc) -- returns the current read/write position within an open file
- [LOF](LOF) -- returns the size, in bytes, of an open file
- [MkDir](MkDir) -- creates a new directory or folder
- [CurDir](CurDir) -- returns the current path
- [Reset](Reset) -- closes all disk files opened by using the **Open** statement
- [RmDir](RmDir) -- removes an existing directory or folder
- [Seek](Seek) -- returns or sets the read/write position within an open file
Expand Down
Loading