루아 레퍼런스 매뉴얼 — 독립형 인터프리터

루아 레퍼런스 매뉴얼 — 독립형 인터프리터 (Lua Standalone)

원래 루아는 호스트 프로그램(C)에 끼워 넣어 쓰는 확장 언어로 설계됐어요. 그런데 실제로는 독립된 하나의 언어로도 아주 많이 쓰이죠. 그래서 루아를 그냥 혼자서 돌릴 수 있는 인터프리터를 따로 제공해요. 이름은 간단하게 lua라고 해요. 표준 배포판(standard distribution)에 딸려 오고, 모든 표준 라이브러리를 포함하고 있답니다. 실행 방식은 이렇게 생겼어요.

lua [options] [script [args]]

출처: Lua 5.4 Reference Manual — 7 Lua Standalone (https://www.lua.org/manual/5.4/manual.html)

본문

lua가 받을 수 있는 옵션은 다음과 같아요.

  • -e _stat_: 문자열 _stat_을(를) 실행해요.
  • -i: _script_(을)를 실행한 뒤 대화형(interactive) 모드로 들어가요.
  • -l _mod_: _mod_(을)를 require하고, 그 결과를 전역 변수 _mod_에 저장해요.
  • -l _g=mod_: _mod_(을)를 require하고, 그 결과를 전역 변수 _g_에 저장해요.
  • -v: 버전 정보를 출력해요.
  • -E: 환경 변수를 무시해요.
  • -W: 경고(warnings)를 켜요.
  • --: 옵션 처리를 멈춰요.
  • -: stdin을 파일처럼 실행하고, 옵션 처리를 멈춰요.

-l _g=mod_ 형태는 릴리스 5.4.4에서 도입됐어요.

옵션을 처리한 다음에는 lua가 주어진 _script_(를)를 실행해요. 인자 없이 실행하면 상황에 따라 동작이 달라져요. 표준 입력(stdin)이 터미널이면 lua -v -i처럼 동작하고, 그렇지 않으면 lua -처럼 동작해요.

-E 옵션 없이 실행할 때는, 인터프리터가 아무 인자나 실행하기 전에 환경 변수를 확인해요. 확인하는 변수는 LUA_INIT_5_4이고, 버전이 붙은 이름이 정의되어 있지 않으면 LUA_INIT을 확인해요. 변수 내용이 @_filename_ 형태라면 lua는 그 파일을 실행하고, 그게 아니면 문자열 자체를 실행해요.

반대로 -E 옵션을 주면 루아는 어떤 환경 변수도 참조하지 않아요. 특히 package.pathpackage.cpath의 값이 luaconf.h에 정의된 기본 경로로 설정돼요. 이 옵션이 켜져 있다는 걸 라이브러리들이 알 수 있도록, 독립형 인터프리터는 레지스트리(registry)의 "LUA_NOENV" 필드를 true 값으로 설정해요. 그러면 다른 라이브러리들도 같은 목적으로 이 필드를 참조할 수 있어요.

-e, -l, -W 옵션은 나타난 순서대로 처리돼요. 예를 들어 이런 호출을 보면,

$ lua -e 'a=1' -llib1 script.lua

먼저 a를 1로 설정하고, 그다음 라이브러리 lib1을 require하고, 마지막에 파일 script.lua를 인자 없이 실행해요. (여기서 $는 셸 프롬프트예요. 여러분 셸의 프롬프트는 다를 수 있어요.)

어떤 코드를 실행하기 전에, lua는 모든 명령줄 인자를 전역 테이블인 arg에 모아둬요. 스크립트 이름은 인덱스 0에, 스크립트 이름 다음에 오는 첫 번째 인자는 인덱스 1에 가는 식이에요. 스크립트 이름보다 앞에 있는 인자(즉 인터프리터 이름과 그 옵션들)는 음수 인덱스로 들어가요. 예를 들어 이런 호출에서는,

$ lua -la b.lua t1 t2

테이블이 이렇게 돼요.

arg = { [-2] = "lua", [-1] = "-la",
             [0] = "b.lua",
             [1] = "t1", [2] = "t2" }

호출에 스크립트가 없으면 인터프리터 이름이 인덱스 0에 가고, 그 뒤에 나머지 인자들이 이어져요. 예를 들어 아래 호출은 -e를 출력해요.

$ lua -e "print(arg[1])"

스크립트가 있으면 그 스크립트는 arg[1], ···, arg[#arg]를 인자로 받아 호출돼요. 루아의 모든 청크(chunk)와 마찬가지로, 스크립트도 가변 인자 함수(variadic function)로 컴파일돼요.

대화형 모드에서는 루아가 반복해서 프롬프트를 띄우고 한 줄을 기다려요. 한 줄을 읽은 뒤, 루아는 먼저 그 줄을 **표현식(expression)**으로 해석해 봐요. 성공하면 그 값을 출력하고, 아니면 그 줄을 문장(statement)으로 해석해요. 문장이 불완전하면 인터프리터는 다른 프롬프트를 내보내며 그 완성을 기다려요.

전역 변수 _PROMPT에 문자열이 들어 있으면 그 값이 프롬프트로 쓰여요. 마찬가지로 전역 변수 _PROMPT2에 문자열이 들어 있으면 그 값이 보조 프롬프트로 쓰이는데, 이건 불완전한 문장이 나올 때 사용돼요.

스크립트에서 보호되지 않은 오류(unprotected error)가 나면 인터프리터는 그 오류를 표준 오류 스트림(standard error stream)에 보고해요. 오류 객체가 문자열이 아니라 __tostring 메타메서드를 갖고 있으면, 인터프리터가 그 메타메서드를 호출해서 최종 메시지를 만들어요. 그게 아니라면 오류 객체를 문자열로 바꾸고 여기에 스택 역추적(stack traceback)을 덧붙여요. 경고가 켜져 있으면 경고는 그저 표준 오류 출력에 출력돼요.

정상적으로 끝날 때는 인터프리터가 자체 메인 루아 상태(main Lua state)를 닫아요 (lua_close 참조). 스크립트가 이 단계를 건너뛰고 싶으면 os.exit를 호출해서 종료하면 돼요.

유닉스 시스템에서 루아를 스크립트 인터프리터로 쓸 수 있도록, 루아는 파일 청크의 첫 줄이 #로 시작하면 그 줄을 건너뛰어요. 그래서 루아 스크립트는 chmod +x#! 형태를 쓰면 실행 가능한 프로그램으로 만들 수 있어요. 이렇게요.

#!/usr/local/bin/lua

물론 루아 인터프리터의 위치는 여러분 머신마다 다를 수 있어요. luaPATH에 있다면,

#!/usr/bin/env lua

이쪽이 더 이식성이 좋은(portable) 해법이에요.

더 알아보기

  • 챕터 6 — Lua 표준 라이브러리 (Lua Standard Libraries)
  • 챕터 8 — Incompatibilities with the Previous Version (이전 버전과의 호환성)
  • lua 실행 파일의 소스는 루아 표준 배포판의 lua.c에서 확인할 수 있어요.